Tags: frontend

1647

sparkline

Saturday, June 6th, 2020

Hybrid positioning with CSS variables and max() – Lea Verou

Yet another clever technique from Lea. But I’m also bookmarking this one because of something she points out about custom properties:

The browser doesn’t know if your property value is valid until the variable is resolved, and by then it has already processed the cascade and has thrown away any potential fallbacks.

That explains an issue I was seeing recently! I couldn’t understand why an older browser wasn’t getting the fallback I had declared earlier in the CSS. Turns out that custom properties mess with that expectation.

Monday, June 1st, 2020

Global and Component Style Settings with CSS Variables — Sara Soueidan

Sara shares how she programmes with custom properties in CSS. It sounds like her sensible approach aligns quite nicely with Andy’s CUBE CSS methodology.

Oh, and she’s using Fractal to organise her components:

I’ve been using Fractal for a couple of years now. I chose it over other pattern library tools because it fit my needs perfectly — I wanted a tool that was unopinionated and flexible enough to allow me to set up and structure my project the way I wanted to. Fractal fit the description perfectly because it is agnostic as to the way I develop or the tools I use.

Sass Color Functions in CSS | Jim Nielsen’s Weblog

I’m not the only one swapping out Sass with CSS for colour functions:

Because of the declarative nature of CSS, you’re never going to get something as terse as what you could get in Sass. So sure, you’re typing more characters. But you know what you’re not doing? Wrangling build plugins and updating dependencies to get Sass to build. What you write gets shipped directly to the browser and works as-is, now and for eternity. It’s hard to say that about your Sass code.

Saturday, May 30th, 2020

Programming CSS to perform Sass colour functions

I wrote recently about moving away from Sass to using native CSS features. I had this to say on the topic of mixins in Sass:

These can be very useful, but now there’s a lot that you can do just in CSS with calc(). The built-in darken() and lighten() mixins are handy though when it comes to colours.

I know we will be getting these in the future but we’re not there yet with CSS.

Anyway, I had all this in the back of my mind when I was reading Lea’s excellent feature in this month’s Increment: A user’s guide to CSS variables. She’s written about a really clever technique of combining custom properites with hsl() colour values for creating colour palettes. (See also: Una’s post on dynamic colour theming with pure CSS.)

As so often happens when I’m reading something written by Lea—or seeing her give a talk—light bulbs started popping over my head (my usual response to Lea’s knowledge bombs is either “I didn’t know you could do that!” or “I never thought of doing that!”).

I immediately set about implementing this technique over on The Session. The trick here is to use separate custom properties for the hue, saturation, and lightness parts of hsl() colour values. Then, when you want to lighten or darken the colour—say, on hover—you can update the lightness part.

I’ve made a Codepen to show what I’m doing.

Let’s say I’m styling a button element. I make custom propertes for hsl() values:

button {
  --button-colour-hue: 19;
  --button-colour-saturation: 82%;
  --button-colour-lightness: 38%;
  background-color: hsl(
    var(--button-colour-hue),
    var(--button-colour-saturation),
    var(--button-colour-lightness)
  );
}

For my buttons, I want the borders to be slightly darker than the background colour. When I was using Sass, I used the darken() function to this. Now I use calc(). Here’s how I make the borders 10% darker:

border-color: hsl(
  var(--button-colour-hue),
  var(--button-colour-saturation),
  calc(var(--button-colour-lightness) - 10%)
);

That calc() function is substracting a percentage from a percentage: 38% minus 10% in this case. The borders will have a lightness of 28%.

I make the bottom border even darker and the top border lighter to give a feeling of depth.

On The Session there’s a “cancel” button style that’s deep red.

Here’s how I set its colour:

.cancel {
  --button-colour-hue: 0;
  --button-colour-saturation: 100%;
  --button-colour-lightness: 40%;
}

That’s it. The existing button declarations take care of assigning the right shades for the border colours.

Here’s another example. Site admins see buttons for some actions only available to them. I want those buttons to have their own colour:

.admin {
  --button-colour-hue: 45;
  --button-colour-saturation: 100%;
  --button-colour-lightness: 40%;
}

You get the idea. It doesn’t matter how many differently-coloured buttons I create, the effect of darkening or lightening their borders is all taken care of.

So it turns out that the lighten() and darken() functions from Sass are available to us in CSS by using a combination of custom properties, hsl(), and calc().

I’m also using this combination to lighten or darken background and border colours on :hover. You can poke around the Codepen if you want to see that in action.

I love seeing the combinatorial power of these different bits of CSS coming together. It really is a remarkably powerful programming language.

Global CSS options with custom properties | @mdo

This is clever—using custom properties to enable if/else logic in CSS.

Friday, May 29th, 2020

CUBE CSS - Piccalilli

I really, really like Andy’s approach here:

The focus of the methodology is utilising the power of CSS and the web platform as a whole, with some added controls and structures that help to keep things a bit more maintainable and predictable. The end-goal is shipping as little CSS as possible—leaning heavily into progressive enhancement and modern techniques.

If you use the cascade for everything, you’re going to run into trouble. But equally, micro-managing styles on every element will also get you into trouble. I think Andy’s found a really great sweet spot here that gets the balance just right.

CUBE CSS in essence, is a progressive enhancement approach, vs a fight against the grain of CSS or a pixel-pushing your project to within an inch of its life approach.

Yes! It feels very “webby” to me.

Increment: Frontend

This month’s issue of Increment is all about front-end development. There are feaures from Lea Verou, Chris Coyier, Chris Lilley, Safia Abdalla, and more.

A Guide to the Responsive Images Syntax in HTML | CSS-Tricks

Chris has put together one of his indispensable deep dives, this time into responsive images. I can see myself referring back to this when I need to be reminded of the syntax of srcset and sizes.

Tuesday, May 26th, 2020

as days pass by — Browsers are not rendering engines

You see, diversity of rendering engines isn’t actually in itself the point. What’s really important is diversity of influence: who has the ability to make decisions which shape the web in particular ways, and do they make those decisions for good reasons or not so good?

Stuart responds to a post from Brian that was riffing off a post of mine from a while back. I like this kind of social network.

S01E04: Cassie Evans - Behind the Source

This is a lovely little interview with Cassie—it really is an honour and a privilege to work with her!

Today’s Javascript, from an outsider’s perspective | Lea Verou

This is a damning and all-too typical example of what it’s like for someone to trying to get to grips with the current state of the JavaScript ecosystem:

Note that John is a computer scientist that knows a fair bit about the Web: He had Node & npm installed, he knew what MIME types are, he could start a localhost when needed. What hope do actual novices have?

I think it’s even worse than that. Not only are potential new devs being put off ever getting started, I know plenty of devs with experience who have pushed out by the overwhelming and needless complexity of the modern web’s toolchain. It’s like a constant gaslighting where any expression of unease is summarily dismissed as being the whinings of “the old guard” who just won’t get with the programme.

John gives up. Concludes never to touch Node, npm, or ES6 modules with a barge pole.

The End.

(Just watch as Lea’s post gets written off as an edge case.)

Responsive web design turns ten. — Ethan Marcotte

2010 was quite a year:

And exactly three weeks after Jeremy Keith’s HTML5 For Web Designers was first published, “Responsive Web Design” went live in A List Apart.

Nothing’s been quite the same since.

I remember being at that An Event Apart in Seattle where Ethan first unveiled the phrase and marvelling at how well everything just clicked into place, perfectly capturing the zeitgeist. I was in. 100%.

Saturday, May 23rd, 2020

Lightning-Fast Web Performance: an online lecture series from Scott Jehl

Scott is brilliant, therefore by the transitive property, his course on web performance must also be brilliant.

Monday, May 18th, 2020

Hard to break

I keep thinking about some feedback that Cassie received recently.

She had delivered the front-end code for a project at Clearleft, and—this being Cassie we’re talking about—the code was rock solid. The client’s Quality Assurance team came back with the verdict that it was “hard to break.”

Hard to break. I love that. That might be the best summation I’ve heard for describing resilience on the web.

If there’s a corollary to resilient web design, it would be brittle web design. In a piece completely unrelated to web development, Jamais Cascio describes brittle systems:

When something is brittle, it’s susceptible to sudden and catastrophic failure.

That sounds like an inarguably bad thing. So why would anyone end up building something in a brittle way? Jamais Cascio continues:

Things that are brittle look strong, may even be strong, until they hit a breaking point, then everything falls apart.

Ah, there’s the rub! It’s not that brittle sites don’t work. They work just fine …until they don’t.

Brittle systems are solid until they’re not. Brittleness is illusory strength. Things that are brittle are non-resilient, sometimes even anti-resilient — they can make resilience more difficult.

Kilian Valkhof makes the same point when it comes to front-end development. For many, accessibility is an unknown unknown:

When you start out it’s you, notepad and a browser against the world. You open up that notepad, and you type

<div onclick="alert('hello world');">Click me!</div>

You fire up your browser, you click your div and …it works! It just works! Awesome. You open up the devtools. No errors. Well done! Clearly you did a good job. On to the next thing.

At the surface level, there’s no discernable difference between a resilient solution and a brittle one:

For all sorts of reasons, both legitimate and, as always, weird browser legacy reasons, a clickable div will mostly work. Well enough to fool someone starting out anyway.

If everything works, how would they know it kinda doesn’t?

Killian goes on to suggest ways to try to make this kind of hidden brittleness more visible.

Furthermore we could envision a browser that is much stricter when developing.

This something I touched on when I was talking about web performance with Gerry on his podcast:

There’s a disconnect in the process we go through when we’re making something, and then how that thing is experienced when it’s actually on the web, which is dependent on network speeds and processing speeds and stuff.

I spend a lot of time wondering why so many websites are badly built. Sure, there’s a lot can be explained by misaligned priorities. And it could just be an expression of Sturgeon’s Law—90% of websites are crap because 90% of everything is crap. But I’ve also come to realise that even though resilience is the antithesis to brittleness, they both share something in common: they’re invisible.

We have a natural bias towards what’s visible. Being committed to making sure something is beautiful to behold is, in some ways, the easy path to travel. But being committed to making sure something is also hard to break? That takes real dedication.

Wednesday, May 13th, 2020

Modern CSS Solutions

…for old CSS problems.

Very handy!

Reef

This micro libarary does DOM diffing in native JavaScript:

Reef is an anti-framework.

It does a lot less than the big guys like React and Vue. It doesn’t have a Virtual DOM. It doesn’t require you to learn a custom templating syntax. It doesn’t provide a bunch of custom methods.

Reef does just one thing: render UI.

Sass and clamp

CSS got some pretty nifty features recently. There’s the min() and max() functions. If you use them for, say, width you can use one rule where previously you would’ve needed to use two (a width declaration followed by either min-width or max-width). But they can also be applied to font-size! That’s very nifty—we’ve never had min-font-size or max-font-size properties.

There’s also the clamp() function. That allows you to set a minimum size, a default size, and a maximum size. Again, it can be used for lengths, like width, or for font-size.

Over on thesession.org, I’ve had some media queries in place for a while now that would increase the font-size for larger screens. It’s nothing crucial, just a nice-to-have so that on wide screens, the font is bumped up accordingly. I realised I could replace all those media queries with one clamp() statement, thanks to the vw (viewport width) unit:

font-size: clamp(1rem, 1.333vw, 1.5rem);

By default, the font-size is 1.333vw (1.333% of the viewport width), but it will never get smaller than 1rem and it will never get larger than 1.5rem.

That works, but there’s a bit of an issue with using raw vw units like that. If someone is on a wide screen and they try to adjust the font size, nothing will happen. The viewport width doesn’t change when you bump the font size up or down.

The solution is to mix in some kind of unit that does respond to the font size being bumped up or down (like, say, the rem unit). Handily, clamp() allows you to combine units, just like calc(). So I can do this:

font-size: clamp(1rem, 0.5rem + 0.666vw, 1.5rem);

The result is much the same as my previous rule, but now—thanks to the presence of that 0.5rem value—the font size responds to being adjusted by the user.

You could use a full 1rem in that default value:

font-size: clamp(1rem, 1rem + 0.333vw, 1.5rem);

…but if you do that, the minimum size (1rem) will never be reached—the default value will always be larger. So in effect it’s no different than saying:

font-size: min(1.rem + 0.333vw, 1.5rem);

I mentioned this to Chris just the other day.

Anyway, I got the result I wanted. I wanted the font size to stay at the browser default size (usually 16 pixels) until the screen was larger than around 1200 pixels. From there, the font size gets gradually bigger, until it hits one and a half times the browser default (which would be 24 pixels if the default size started at 16). I decided to apply it to the :root element (which is html) using percentages:

:root {
  font-size: clamp(100%, 50% + 0.666vw, 150%);
}

(My thinking goes like this: if we take a screen width of 1200 pixels, then 1vw would be 12 pixels: 1200 divided by 100. So for a font size of 16 pixels, that would be 1.333vw. But because I’m combining it with half of the default font size—50% of 16 pixels = 8 pixels—I need to cut the vw value in half as well: 50% of 1.333vw = 0.666vw.)

So I’ve got the CSS rule I want. I dropped it in to the top of my file and…

I got an error.

There was nothing wrong with my CSS. The problem was that I was dropping it into a Sass file (.scss).

Perhaps I am showing my age. Do people even use Sass any more? I hear that post-processors usurped Sass’s dominance (although no-one’s ever been able to explain to me why they’re different to pre-processers like Sass; they both process something you’ve written into something else). Or maybe everyone’s just writing their CSS in JS now. I hear that’s a thing.

The Session is a looooong-term project so I’m very hesitant to use any technology that won’t stand the test of time. When I added Sass into the mix, back in—I think—2012 or so, I wasn’t sure whether it was the right thing to do, from a long-term perspective. But it did offer some useful functionality so I went ahead and used it.

Now, eight years later, it was having a hard time dealing with the new clamp() function. Specifically, it didn’t like the values being calculated through the addition of multiple units. I think it was clashing with Sass’s in-built ability to add units together.

I started to ask myself whether I should still be using Sass. I looked at which features I was using…

Variables. Well, now we’ve got CSS custom properties, which are even more powerful than Sass variables because they can be updated in real time. Sass variables are like const. CSS custom properties are like let.

Mixins. These can be very useful, but now there’s a lot that you can do just in CSS with calc(). The built-in darken() and lighten() mixins are handy though when it comes to colours.

Nesting. I’ve never been a fan. I know it can make the source files look tidier but I find it can sometimes obfuscate what you’re final selectors are going to look like. So this wasn’t something I was using much any way.

Multiple files. Ah! This is the thing I would miss most. Having separate .scss files for separate interface elements is very handy!

But globbing a bunch of separate .scss files into one .css file isn’t really a Sass task. That’s what build tools are for. In fact, that’s what I was already doing with my JavaScript files; I write them as individual .js files that then get concatenated into one .js file using Grunt.

(Yes, this project uses Grunt. I told you I was showing my age. But, you know what? It works. Though seeing as I’m mostly using it for concatenation, I could probably replace it with a makefile. If I’m going to use old technology, I might as well go all the way.)

I swapped out Sass variables for CSS custom properties, mixins for calc(), and removed what little nesting I was doing. Then I stripped the Sass parts out of my Grunt file and replaced them with some concatenation and minification tasks. All of this makes no difference to the actual website, but it means I’ve got one less dependency …and I can use clamp()!

Remember a little while back when I was making a dark mode for my site? I made this observation:

Let’s just take a moment here to pause and reflect on the fact that we can now use CSS to create all sorts of effects that previously required a graphic design tool like Photoshop.

It feels like something similar has happened with tools like Sass. Sass was the hare. CSS is the tortoise. Sass blazed the trail, but now native CSS can achieve much the same result.

It’s like when we used to need something like jQuery to do DOM Scripting succinctly using CSS selectors. Then we got things like querySelector() in JavaScript so we no longer needed the trailblazer.

I’ve said it before and I’ll say it again, the goal of any good library should be to get so successful as to make itself redundant. That is, the ideas and functionality provided by the tool are so useful and widely adopted that the native technologies—HTML, CSS, and JavaScript—take their cue from those tools.

You could argue that this is what happened with Flash. It certainly happened with jQuery and Sass. I’m pretty sure we’ll see the same cycle play out with frameworks like React.

Tuesday, May 12th, 2020

as days pass by — Hammer and nails

We don’t give people a website any more: something that already works, just HTML and CSS and JavaScript ready to show them what they want. Instead, we give them the bits from which a website is made and then have them compile it.

Spot-on description of “modern” web development. When did this become tolerable, much less normal?

Web developers: maybe stop insisting that your users compile your apps for you? Or admit that you’ll put them through an experience that you certainly don’t tolerate on your own desktops, where you expect to download an app, not to be forced to compile it every time you run it?

Monday, May 11th, 2020

Creating an Accessible Range Slider with CSS | a11y with Lindsey

If you want an accessible slider component, the trick isn’t to use a whole load of JavaScript. The trick is to use the native input type="range" and then figure out the CSS you need (which, alas, involves lots of vendor prefixes).

Second-guessing the modern web - macwright.org

I’m at the point where you look at where the field is and what the alternatives are – taking a second look at unloved, unpopular, uncool things like Django, Rails, Laravel – and think what the heck is happening. We’re layering optimizations upon optimizations in order to get the SPA-like pattern to fit every use case, and I’m not sure that it is, well, worth it.

Spot-on analysis of what React is and isn’t good for. And lest you think this is blasphemy, Dan Abramov agrees.