Frontend Masters Boost RSS Feed https://frontendmasters.com/blog Helping Your Journey to Senior Developer Thu, 15 Aug 2024 13:22:54 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.1 225069128 TUIs https://frontendmasters.com/blog/tuis/ https://frontendmasters.com/blog/tuis/#respond Thu, 15 Aug 2024 13:22:53 +0000 https://frontendmasters.com/blog/?p=3487 I mentioned lazygit the other day, a project I find to have a tremendously well done interface for being entirely at the command line. As frustrated as I get with tmux sometimes (the scrolling and the copying text, ughgkh), I still find it to be useful and impressive that “UI” can exist at all in the terminal.

I’ve since seen Posting, an API client, which also looks amazing. The Charm tools are pretty jaw dropping to me, which include stuff like a Markdown app and email sender. Turns out, there are actually a ton of “TUI” apps, collected here by Justin Garrison. An SQL client, a file manager, and an image viewer, are a few that caught my eye.

]]>
https://frontendmasters.com/blog/tuis/feed/ 0 3487
Relative Color Syntax — Basic Use Cases https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/ https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/#comments Mon, 12 Aug 2024 18:38:35 +0000 https://frontendmasters.com/blog/?p=3448 As of last month, Firefox 128’s support of the relative color syntax means we’ve now got support across the board. I’m excited about that as it’s an extremely powerful way to manipulate colors in CSS. Plus it was part of Interop this year so that is further proof that is trucking along nicely.

The syntax with generic names looks like this:

color-function(from origin-color channel1 channel2 channel3 / alpha)

Here’s how it works in my head:

Add Opacity to a Color you Already Have

It’s common to have CSS custom properties set up for colors on a project.

html {
  --color-yellow: oklch(80% 0.15 94);
  --color-green:  oklch(70% 0.25 140);

  ...
}

Now you want to use that yellow, but at about 50% opacity. How do you do that? There are actually a couple of ways to add transparency to an existing color, but in my opinion the relative color syntax is the nicest.

In the past, I’ve split out the color values like this:

html {
  --color-yellow-lch: 80% 0.15 94;
  --color-yellow: oklch(var(--color-yellow-lch);

  ...
}

That way I could either use the color all together, or use the split out values to apply opacity:

.box {
  background: var(--color-yellow);
  border-color: oklch(var(--color-yellow-lch) / 50%);
}

But that can get out of hand! You could also split each color into L, C, and H, the combine those, giving you five variables for every color. Too much.

With the relative color syntax, breaking down colors isn’t necessary. You apply alpha (and other transformations) on demand, leaving the original single color as the only variable (token) you need.

.box {
  background: var(--color-yellow);
  border-color: oklch(from var(--color-yellow) l c h / 50%); 
}

I much prefer the idea of keeping the main colors tokenized as custom properties, then tweaking them as needed on demand.

Darken a Color you Already Have

In the above example, we had --color-yellow and I ended by saying I prefer doing one-off tweaks on demand rather than making a whole new variable. If you have a ton of usage of a slightly-darker version of a color, then sure, make a new variable and stay consistent. But if it’s more of a one-off, relative color syntax is awesome:

.box {
  background: var(--gray-5);

  h2 {
    color: var(--color-yellow);
    /* Darkened version of yellow */
    border-bottom: 2px solid oklch(from var(--color-yellow) calc(l - 0.4) c h);
  }
}

Lighten a Color you Already Have

Same deal here. I’m using OKLCH because I like it, particularly the “uniform brightness” characteristic. Meaning when doing this darkening and lightening across different colors, it feels like it lightens/darkens the same amount. Which feels weird to write, but it’s true. Other color spaces do not lighten and darken consistently.

.box {
  background: var(--gray-5);

  h2 {
    color: var(--color-orange);
    /* Darkened version of orange */
    border-bottom: 2px solid oklch(from var(--color-orange) calc(l + 0.4) c h);
  }
}

Easy Variations

Avoiding making too many variables is a nice consequence of the relative color syntax, but you can still use the relative color syntax to make variables if it’s useful to have them.

I like the idea of starting with a base color, perhaps a slightly tinted gray, and then making the official variations with the relative color syntax.

html {
  --base-gray: oklch(12.94% 0.02 159);
  
  --gray-1: var(--base-gray);
  --gray-2: oklch(from var(--base-gray) calc(l + 0.1) c h);
  --gray-3: oklch(from var(--base-gray) calc(l + 0.2) c h);
  --gray-4: oklch(from var(--base-gray) calc(l + 0.3) c h);
  --gray-5: oklch(from var(--base-gray) calc(l + 0.4) c h);
  --gray-6: oklch(from var(--base-gray) calc(l + 0.5) c h);
  --gray-7: oklch(from var(--base-gray) calc(l + 0.6) c h);
  --gray-8: oklch(from var(--base-gray) calc(l + 0.7) c h);
}

The fact that you can start with any color, use any color function, and manipulate any part of the color is incredibly powerful. The above use cases are pretty basic. I’m sure more talented designers or developers who deeply know color will be able to do much more interesting things!

]]>
https://frontendmasters.com/blog/relative-color-syntax-basic-use-cases/feed/ 1 3448
It’s Time To Talk About “CSS5” https://frontendmasters.com/blog/its-time-to-talk-about-css5/ https://frontendmasters.com/blog/its-time-to-talk-about-css5/#respond Thu, 08 Aug 2024 14:04:03 +0000 https://frontendmasters.com/blog/?p=3397 Brecht De Ruyte has a good rundown of what’s up with future named versions of CSS. You might remember “CSS3” and how hot of a buzzword that is. JavaScript still has successful “ES202X” naming that groups features into useful buckets. But CSS hasn’t benefited from named groups since CSS3.

I’ve written:

CSS3, and perhaps to a larger degree, “HTML5”, became (almost) household names. It was so successful, it’s leaving us wanting to pull that lever again. It was successful on a ton of levels:

  • It pushed browser technology forward, particularly on technologies that had been stale for too long.
  • It got site owners to think, “hey maybe it’s a good time to update our website.
  • It got educators to think, “hey maybe it’s a good time to update our curriculums.

Then it felt like a pipedream. Now it’s real! You can see how the official community group is grouping CSS features and comment on the RFC (Request for Comments). I take no issues with the groups. Ship it.

]]>
https://frontendmasters.com/blog/its-time-to-talk-about-css5/feed/ 0 3397
Scaling One Million Checkboxes https://frontendmasters.com/blog/scaling-one-million-checkboxes/ https://frontendmasters.com/blog/scaling-one-million-checkboxes/#respond Tue, 06 Aug 2024 14:06:37 +0000 https://frontendmasters.com/blog/?p=3386 Nolen Royalty made a website (now turned off) with a million checkboxes on it which was realtime for everyone viewing it. Users can check (or uncheck) a checkbox and that is persisted to a datastore and propagated to all visitors instantly. This, as it turns out, is a non-trivial task if you want it to run well, handle scale, and not cost a ton of money.

I’m posting this because if reading this kind of thing is interesting and kind of thrilling for you, a career in DevOps is probably not a bad idea for you.

]]>
https://frontendmasters.com/blog/scaling-one-million-checkboxes/feed/ 0 3386
What if you used Container Units for… everything? https://frontendmasters.com/blog/what-if-you-used-container-units-for-everything/ https://frontendmasters.com/blog/what-if-you-used-container-units-for-everything/#respond Fri, 02 Aug 2024 16:49:11 +0000 https://frontendmasters.com/blog/?p=3108 I said to myself I said what if I used container units for every single unit in a design? I was wondering, partially because I thought the answer might be well, everything will probably scale really nicely then. Container units, in case you haven’t heard of them, are unit (like px or rem, but more closely related to viewport units like vw or vi) that are sized relatively to the container that they are in.

Turns out, surprise surprise, that it’s not that easy. There are plenty of things that container queries are awkward at or just not the right unit for.

I had a play with a pretty simple grid of cards of various sizes. Don’t consider this demo in good shape, it’s just what I used to have a plan.

Potential Problem: You Can’t Style The Element You Query

This is a fairly known thing with container queries, but the weirdness with it compounds a bit with container units, as the desire to use those units right away on a container is strong. To be clear, the container units will “work”, they’ll just be based on the next-higher-up container, which if there isn’t a declared one will be the document.

.card-wrap {
  container: cardWrap / inline-size;

  padding: 2cqi;
  border-radius: 4cqi;

  .card {
    border-radius: 4cqi;
  }
}

Above, the border-radius will be different despite looking like it will be the same, because the container the units reference are different.

See how the outer border radius’ match, but the inner card are different and look off on the larger card.

Potential Solution: Style Nothing on the Container

Be vigilant! It will save headaches if you are hardfast when you set a container you do no other size-based styling. If that means adding an extra otherwise meaningless <div> wrapper, well, that’s not ultra ideal as DOM weight does matter, but it’s probably fine.

Potential Problem: Too Small & Too Big

If you only use container units for something like font-size, it’s pretty easy to get into a situation where text, and text-based elements, end up either too big or too small.

Here the text on the larger card feels a bit too big but the tags are OK. The text on the smaller card feels OK, but those tags are too small.

Either is annoying, but too small is also an accessibility failure.

Using container units (or viewport units) alone is a bad practice for text sizing. It’s fixable though.

Potential Solution: Clamp

Making sure text doesn’t get too small or too big is solved with a CSS clamp() function. And while we’re at it, we can sprinkle in a relative unit to make sure that users font sizing preferences are honored.

You can still use container units, but set those limits and use a bit of relative mixed in.

.tag {
  /* Don't */
  font-size: 4cqi;

  /* Do */
  font-size: clamp(16px, 4cqi + 0.5rem, 24px);
}

Potential Problem: Rows vs Columns

One strong use case for a container query is shifting layout at container based breakpoints. If that container goes from wide-and-short to narrow-and-tall, then the width-based (probably the most common) container units will be super different.

Say the container here is the card itself, and you size some icons to work with that context when they are horizontal. But then if you shift the layout to a narrow column for the icons, as the card gets bigger, the sizing doesn’t work in that context now.

Bonus problem: you can’t use container units to set the grid-template-columns as they can never be based on an element that is reliably the same width as the grid.

Instead, if we make the element around the icons the container, and thus it changes width when the layout changes, the change in our icon size can be too dramatic.

Potential Solution: Use a Different Unit

And here’s the rub. You just don’t have to use container units for everything. I doubt anyone ever intended for them to be used that way. It’s just a fun exercise, especially as strong scalability is a great effect.

In this case maybe something like cqmax units would be workable, so the unit is based on the containers longest edge.

.actions {
  container: actions / inline-size;

  svg {
    display: block;
    width: 4cqmax;
    min-width: 24px;
    max-width: 100%;
    aspect-ratio: 1;
  }
}

But… nah. It’s too weird. I’d say just use relative units or pixels or something here.

In the end, if container units are helpful for a scaling effect based on the size of an element you want to achieve, go for it! The support is good. But don’t force it.

If you’re up for a challenge, have a play with it. Try something like converting every unit in a more complex layout like this into containers with container units.

]]>
https://frontendmasters.com/blog/what-if-you-used-container-units-for-everything/feed/ 0 3108
So you think you know box shadows? https://frontendmasters.com/blog/so-you-think-you-know-box-shadows/ https://frontendmasters.com/blog/so-you-think-you-know-box-shadows/#respond Thu, 01 Aug 2024 14:35:32 +0000 https://frontendmasters.com/blog/?p=3322 David Gerrells has a bunch of fun rendering far too many CSS box-shadows for things that box-shadow was never meant to do.

I found out my m1 can render a stupid number of these bad boys and so I set out to see just how far you can push them and boy did I.

Because box-shadow mimics the shape of the original element, doesn’t have to have any blur at all, and can be colored any color, they can be a way to draw anything you want wherever you want with a single DOM element. Doing faux ray-tracing as David does at the end is not something I thought I’d ever see.

I found it fun looking at the DevTools while the demos were cooking.

]]>
https://frontendmasters.com/blog/so-you-think-you-know-box-shadows/feed/ 0 3322
SVG triangle of compromise https://frontendmasters.com/blog/svg-triangle-of-compromise/ https://frontendmasters.com/blog/svg-triangle-of-compromise/#respond Tue, 30 Jul 2024 15:15:04 +0000 https://frontendmasters.com/blog/?p=3290 tag, it’s cached nicely, but you give up on CSS […]]]> I enjoyed Micah R Ledbetter’s SVG triangle of compromise and generally think it’s a fair analysis of how any-which-way you use SVG on a page, you’re giving up some kind of nice ability it could have. For instance, if you use SVG through an <img> tag, it’s cached nicely, but you give up on CSS reaching in there to style things. If you drop it in as <svg>, you can style, but then it’s not cached well for repeated uses.

Then Scott Jehl chimed in with a way to “have it all”. The crux of it is using the SVG <use> element to reference an SVG file (so you get caching and sizing) and you can set CSS --custom-properties that “pierce” the shadow DOM that <use> creates (that’s right, SVG can have a shadow DOM just like web components) and allow for styling.

This does solve all three angles, the caveats being 1) you can’t cache the SVG (“sprite”, it’s usually called when you combine icons into a single file) on a different domain. 2) it’s a manual pain to set up SVGs to be entirely styled in this way. Scott’s tool might help with 2, but browsers need to help with 1.

]]>
https://frontendmasters.com/blog/svg-triangle-of-compromise/feed/ 0 3290
Blurring https://frontendmasters.com/blog/blurring/ https://frontendmasters.com/blog/blurring/#respond Fri, 26 Jul 2024 19:31:08 +0000 https://frontendmasters.com/blog/?p=3194 , to WebGL. I particularly like the idea of masking an element with a backdrop-filter with a gradient so, for instance, a header can fade out how much […]]]> This 9-minute video from Juxtopposed on blurring is a great watch. There are an awful lot of ways to blur things on the web, from filter, backdrop-filter, <feGaussianBlur>, to WebGL. I particularly like the idea of masking an element with a backdrop-filter with a gradient so, for instance, a header can fade out how much blur is being applied.

]]>
https://frontendmasters.com/blog/blurring/feed/ 0 3194
Ladybird & Independent Browser Engines https://frontendmasters.com/blog/ladybird/ https://frontendmasters.com/blog/ladybird/#comments Wed, 24 Jul 2024 17:41:41 +0000 https://frontendmasters.com/blog/?p=3132 Web browsers are tens of millions of lines of code written over decades to adhere to long, complex standards specifications and defend against all manner of malicious behavior. I’ve long been convinced that an entirely new browser (not a fork or a skinning) would be impossible to build today. Just scratch pad math, maybe 100 developers making 100k/year could do it over 5 years, so call it a 50m investment on developer power alone. Who ponies that up and why?

Well, Ladybird is giving it a go. They should have 7 full timers soon, and it’s open source so they’ll get help there, and are taking donations. Plus they’ll use some third-party resources to get it done, which should trim down on requirements. It reads like the thing already runs. Their big why is that Google is just too influential — and of course there is already controversy.

There is also Flow as well as Servo, which I’m told is the furthest along of all of them. They should get together on all this if you ask me. I’m happy to admit I was wrong and that it seems like new browser engines aren’t the fiction I thought they were.

]]>
https://frontendmasters.com/blog/ladybird/feed/ 1 3132
Clip Pathing Color Changes https://frontendmasters.com/blog/clip-pathing-color-changes/ https://frontendmasters.com/blog/clip-pathing-color-changes/#respond Tue, 23 Jul 2024 17:29:41 +0000 https://frontendmasters.com/blog/?p=3103 This is a nice post from Emil Kowalski on usage of the clip-path property in CSS. I’ve always liked clip-path. Maybe it’s because it’s such a sharp knife. When you clip an element, it’s clipped, yo. There isn’t a lot of nuance to it, it does what it does. But moreso, I think I like the connection to SVG (oh, hey, by the way, I just made my old book Practical SVG entirely free). The value that you give clip-path is stuff like circle(), polygon(), path(), etc — the primitive shapes of SVG.

In Emil’s post, my favorite example is a navigation bar where a “pill” shape animates from one navigation item to another when they are clicked. The pill is a different background color, and so the text color also changes. (If you’re over 100 years old like me, we used to call this kind of thing “lava lamp” navigation 👴).

I would guess most people would assume what is happening here is an extra element set behind the links that moves position to underneath the newly active links. You could do it that way, but there is a minor aesthetic issue with it. Because the background-color is changing here, the text also needs to change appropriately (from dark to light here). You could change that color instantly, but that will look weird like it’s changing too early. You could set a transition on it, but you’ll never get the fade to look quite right, especially as it has to go through an awkward gray color.

Essentially, you’ll never get a state like this:

This ain’t gonna happen with an underlay element alone.

See how the text is half-light and half-dark mid-animation when the highlight blue pill moves from one to another? That’s a lovely effect that makes this feel very polished and smooth. This idea first came from a tweet by Paco. Like Emil says:

You might say that not everyone is going to notice the difference, but I truly believe that small details like this add up and make the experience feel more polished. Even if they go unnoticed.

Agreed.

In Emil’s post, it’s done with React. That’s totally fine, but I figured I’d make a vanilla one for y’all here:

Here’s how this works:

  1. There is one set of semantic HTML navigation.
  2. If JavaScript executes, it duplicates the nav (we’ll need two) but ensures the duplicate is hidden for screen readers.
  3. The duplicate is placed exactly on top of the original (it’s the “blue” one) and can’t directly be clicked (i.e. pointer-events: none;)
  4. A clip-path is set that highlights one of the navigation items in particular by clipping the entire duplicate except one link.
  5. As links are clicked, the clip-path is changed using positional math, highlighting the new one. Also high-five for the round keyword that can be used with inset() for rounded corners on inset rectangles.
  6. The clip-path animates, thanks to a basic CSS transition.

I think it’s cool as heck that it all comes together that cleanly.

It’s also a nice touch that the new clip-path positions are calculated based on their page position, meaning that there are really no magic numbers here. If we add navigation items or change them, this code will be resilient and it will all still work. And if none of this JavaScript runs at all, no big deal.

]]>
https://frontendmasters.com/blog/clip-pathing-color-changes/feed/ 0 3103