Tech News

Five 5-minute Videos from Ethan on Design & Accessibility

Css Tricks - Tue, 06/30/2020 - 4:34am


I’ve been working with Aquent Gymnasium to produce a series of five short tutorial videos, which have been launching over the course of this past week. Since the last video just went live, I’m thrilled to share the whole list with you:

Introduction to using VoiceOver on macOS
Designing beautiful focus states
Flexible and accessible typesetting
Responsively designing with viewport units
Designing beautiful and accessible drop caps

Five minutes is a real sweet spot for a how-to video. Ain’t no time to screw around. I loved every minute of these.

Direct Link to ArticlePermalink

The post Five 5-minute Videos from Ethan on Design & Accessibility appeared first on CSS-Tricks.

When Sass and New CSS Features Collide

Css Tricks - Mon, 06/29/2020 - 4:56am

Recently, CSS has added a lot of new cool features such as custom properties and new functions. While these things can make our lives a lot easier, they can also end up interacting with preprocessors, like Sass, in funny ways.

So this is going to be a post about the issues I’ve encountered, how I go around them, and why I still find Sass necessary these days.

The errors

If you’ve played with the new min() and max() functions, you may have ran into an error message like this when working with different units: “Incompatible units: vh and em.”

An error when working with different types of units in the min()/ max() function

This is because Sass has its ownmin() function, and ignores the CSS min() function. Plus, Sass cannot perform any sort of computation using two values with units that don’t have a fixed relation between them.

For example, cm and in units have a fixed relation between them, so Sass can figure out what’s the result of min(20in, 50cm) and doesn’t throw an error when we try to use it in our code.

The same things goes for other units. Angular units, for example, all have a fixed relation between them: 1turn, 1rad or 1grad always compute to the same deg values. Same goes for 1s which is always 1000ms, 1kHz which is always 1000Hz, 1dppx which is always 96dpi, and 1in which is always 96px. This is why Sass can convert between them and mix them in computations and inside functions such as its own min() function.

But things break when these units don’t have a fixed relation between them (like the earlier case with em and vh units).

And it’s not just different units. Trying to use calc() inside min() also results in an error. If I try something like calc(20em + 7px), the error I get is, “calc(20em + 7px) is not a number for min.”

An error when using different unit values with calc() nested in the min()function

Another problem arises when we want to use a CSS variable or the result of a mathematical CSS function (such as calc(), min() or max()) in a CSS filter like invert().

In this case, we get told that “$color: 'var(--p, 0.85) is not a color for invert.”

var() in filter: invert() error

The same thing happens for grayscale(): “$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale.”

calc() in filter: grayscale() error

opacity() causes the same issue: “$color: ‘var(--p, 0.8)‘ is not a color for opacity.”

var() in filter: opacity() error

However, other filter functions — including sepia(), blur(), drop-shadow(), brightness(), contrast() and hue-rotate()— all work just fine with CSS variables!

Turns out that what’s happening is similar to the min() and max() problem. Sass doesn’t have built-in sepia(), blur(), drop-shadow(), brightness(), contrast(), hue-rotate() functions, but it does have its own grayscale(), invert() and opacity() functions, and their first argument is a $color value. Since it doesn’t find that argument, it throws an error.

For the same reason, we also run into trouble when trying to use a CSS variable that lists at least two hsl()or hsla() values.

var() in color: hsl() error.

On the flip side, color: hsl(9, var(--sl, 95%, 65%)) is perfectly valid CSS and works just fine without Sass.

The exact same thing happens with the rgb()and rgba() functions.

var() in color: rgba() error.

Furthermore, if we import Compass and try to use a CSS variable inside a linear-gradient() or inside a radial-gradient(), we get another error, even though using variables inside conic-gradient() works just fine (that is, if the browser supports it).

var() in background: linear-gradient() error.

This is because Compass comes with linear-gradient() and radial-gradient() functions, but has never added a conic-gradient() one.

The problems in all of these cases arise from Sass or Compass having identically-named functions and assuming those are what we intended to use in our code.


The solution

The trick here is to remember that Sass is case-sensitive, but CSS isn’t.

That means we can write Min(20em, 50vh)and Sass won’t recognize it as its own min() function. No errors will be thrown and it’s still valid CSS that works as intended. Similarly, writing HSL()/ HSLA()/ RGB()/ RGBA() or Invert() allows us to avoid issues we looked at earlier.

As for gradients, I usually prefer linear-Gradient() and radial-Gradient() just because it’s closer to the SVG version, but using at least one capital letter in there works just fine.

But why?

Almost every time I tweet anything Sass-related, I get lectured on how it shouldn’t be used now that we have CSS variables. I thought I’d address that and explain why I disagree.

First, while I find CSS variables immensely useful and have used them for almost everything for the past three years, it’s good to keep in mind that they come with a performance cost and that tracing where something went wrong in a maze of calc() computations can be a pain with our current DevTools. I try not to overuse them to avoid getting into a territory where the downsides of using them outweigh the benefits.

Not exactly easy to figure out what’s the result of those calc() expressions.

In general, if it acts like a constant, doesn’t change element-to-element or state-to-state (in which case custom properties are definitely the way to go) or reduce the amount of compiled CSS (solving the repetition problem created by prefixes), then I’m going to use a Sass variable.

Secondly, variables have always been a pretty small portion of why I use Sass. When I started using Sass in late 2012, it was primarily for looping, a feature we still don’t have in CSS. While I’ve moved some of that looping to an HTML preprocessor (because it reduces the generated code and avoids having to modify both the HTML and the CSS later), I still use Sass loops in plenty of cases, like generating lists of values, stop lists inside gradient functions, lists of points inside a polygon function, lists of transforms, and so on.

Here’s an example. I used to generate n HTML items with a preprocessor. The choice of preprocessor matters less, but I’ll be using Pug here.

- let n = 12; while n-- .item

Then I would set the $n variable into the Sass (and it would have to be equal to that in the HTML) and loop up to it to generate the transforms that would position each item:

$n: 12; $ba: 360deg/$n; $d: 2em; .item { position: absolute; top: 50%; left: 50%; margin: -.5*$d; width: $d; height: $d; /* prettifying styles */ @for $i from 0 to $n { &:nth-child(#{$i + 1}) { transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba); &::before { content: '#{$i}' } } } }

However, this meant that I would have to change both the Pug and the Sass when changing the number of items, making the generated code very repetitive.

CSS generated by the above code

I have since moved to making Pug generate the indices as custom properties and then use those in the transform declaration.

- let n = 12; body(style=`--n: ${n}`) - for(let i = 0; i < n; i++) .item(style=`--i: ${i}`) $d: 2em; .item { position: absolute; top: 50%; left: 50%; margin: -.5*$d; width: $d; height: $d; /* prettifying styles */ --az: calc(var(--i)*1turn/var(--n)); transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az))); counter-reset: i var(--i); &::before { content: counter(i) } } CodePen Embed Fallback

This significantly reduces the generated code.

CSS generated by the above code

However, looping in Sass is still necessary if I want to generate something like a rainbow.

@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) { $unit: 360/$n; $s-list: (); @for $i from 0 through $n { $s-list: $s-list, hsl($i*$unit, $sat, $lum) } @return $s-list } html { background: linear-gradient(90deg, get-rainbow()) } CodePen Embed Fallback

Sure, I could generate it as a list variable from Pug, but doing so doesn’t take advantage of the dynamic nature of CSS variables and it doesn’t reduce the amount of code that gets served to the browser, so there’s no benefit coming out of it.

Another big part of my Sass (and Compass) use is tied to built-in mathematical functions (such as trigonometric functions), which are part of the CSS spec now, but not yet implemented in any browser. Sass doesn’t come with these functions either, but Compass does and this is why I often need to use Compass.

And, sure, I could write my own such functions in Sass. I did resort to this in the beginning, before Compass supported inverse trigonometric functions. I really needed them, so I wrote my own based on the Taylor series. But Compass provides these sorts of functions nowadays and they are better and more performant than mine.

Mathematical functions are extremely important for me as I’m a technician, not an artist. The values in my CSS usually result from mathematical computations. They’re not magic numbers or something used purely for aesthetics. A example is generating lists of clip paths points that create regular or quasi-regular polygons. Think about the case where we want to create things like non-rectangular avatars or stickers.

Let’s consider a regular polygon with vertices on a circle with a radius 50% of the square element we start from. Dragging the slider in the following demo allows us to see where the points are placed for different numbers of vertices:

CodePen Embed Fallback

Putting it into Sass code, we have:

@mixin reg-poly($n: 3) { $ba: 360deg/$n; // base angle $p: (); // point coords list, initially empty @for $i from 0 to $n { $ca: $i*$ba; // current angle $x: 50%*(1 + cos($ca)); // x coord of current point $y: 50%*(1 + sin($ca)); // y coord of current point $p: $p, $x $y // add current point coords to point coords list } clip-path: polygon($p) // set clip-path to list of points }

Note that here we’re also making use of looping and of things such as conditionals and modulo that are a real pain when using CSS without Sass.

A slightly more evolved version of this might involve rotating the polygon by adding the same offset angle ($oa) to the angle of each vertex. This can be seen in the following demo. This example tosses in a star mixin that works in a similar manner, except we always have an even number of vertices and every odd-indexed vertex is situated on a circle of a smaller radius ($f*50%, where $f is sub-unitary):

CodePen Embed Fallback

We can also have chubby stars like this:

CodePen Embed Fallback

Or stickers with interesting border patterns. In this particular demo, each sticker is created with a single HTML element and the border pattern is created with clip-path, looping and mathematics in Sass. Quite a bit of it, in fact.

CodePen Embed Fallback

Another example are these card backgrounds where looping, the modulo operation and exponential functions work together to generate the dithering pixel background layers:

CodePen Embed Fallback

This demo just happens to rely heavily on CSS variables as well.

Then there’s using mixins to avoid writing the exact same declarations over and over when styling things like range inputs. Different browsers use different pseudo-elements to style the components of such a control, so for every component, we have to set the styles that control its look on multiple pseudos.

Sadly, as tempting as it may be to put this in our CSS:

input::-webkit-slider-runnable-track, input::-moz-range-track, input::-ms-track { /* common styles */ }

…we cannot do it because it doesn’t work! The entire rule set is dropped if even one of the selectors isn’t recognized. And since no browser recognises all three of the above, the styles don’t get applied in any browser.

We need to have something like this if we want our styles to be applied:

input::-webkit-slider-runnable-track { /* common styles */ } input::-moz-range-track { /* common styles */ } input::-ms-track { /* common styles */ }

But that can mean a lot of identical styles repeated three times. And if we want to change, say, the background of the track, we need to change it in the ::-webkit-slider-runnable-track styles, in the ::-moz-range-track styles and in the ::-ms-track styles.

The only sane solution we have is to use a mixin. The styles get repeated in the compiled code because they have to be repeated there, but we don’t have to write the same thing three times anymore.

@mixin track() { /* common styles */ } input { &::-webkit-slider-runnable-track { @include track } &::-moz-range-track { @include track } &::-ms-track { @include track } }

The bottom line is: yes, Sass is still very much necessary in 2020.

The post When Sass and New CSS Features Collide appeared first on CSS-Tricks.

Styling Layout Wrappers In CSS

Css Tricks - Mon, 06/29/2020 - 4:55am

Two things that strike me often about the web are how many ways there are to go about the same thing and how many considerations go into even the most seemingly simple things.

Working with wrapper elements is definitely on both those lists. Wrappers (or containers or whatever) are so common — especially when establishing grid layouts and boundaries for the elements inside them — that it’s easy to take them for granted and reach for them without stepping back to consider how they work, why we use them, and how to use them effectively.

Ahmed Shadeed wrote up the most exhaustive article on wrappers I’ve ever read. He provides a brief overview of them before diving into a bunch of considerations and techniques for working with them, including:

  • When to use them
  • How to size them
  • Positioning them
  • Adding margin and padding
  • Working with CSS grid and other display values
  • Breaking out of the wrapper
  • Using CSS custom properties

If you take the images from the article, it tells a pretty cool story.

Direct Link to ArticlePermalink

The post Styling Layout Wrappers In CSS appeared first on CSS-Tricks.

Book: The Greatest CSS Tricks Vol. I

Css Tricks - Mon, 06/29/2020 - 2:57am

Ya know, for a site called “CSS-Tricks” that I’ve run for well over a decade, it’s a little funny we’ve never done a book under that name. I’ve written a book about WordPress and SVG, but never CSS!

Well, allow me to change that. I’ve been working on a “book” called The Greatest CSS Tricks Vol. I, as my attempt to stay true to this site’s name! The big idea is to make it like a coffee-table book for CSS, where each chapter is totally independent and talks about one literal CSS trick that I’ve found to be exceptionally clever and useful — a book about quite literally the best CSS tricks I’ve come across over the years.

I quoted the word “book” above because this is the loosest possible definition of a book. I have not yet made it into an eBook format. I have not even considered printing it yet (although there is a “full book” URL available with the whole book together for printing and print-to-PDFing). This book exists as URLs which are essentially fancy blog posts grouped together. I’m also calling it Volume I as there are already ideas for another one!

Some chapters are broadly known concepts that I’ve written up. But many of the chapters are based on ideas that can be traced back to individual people and I always try to credit them directly.

Here’s the chapter list so far:

  1. Pin Scrolling to Bottom
  2. Scroll Animation
  3. Yellow Flash
  4. Shape Morphing
  5. Flexible Grids
  6. Border Triangles
  7. Scroll Indicator
  8. Boxy Buttons
  9. Self-Drawing Shapes
  10. Perfect Font Fallbacks
  11. Scroll Shadows
  12. Editable Style Blocks
  13. Draggable Elements
  14. Hard Stop Gradients
  15. Squigglevision

I say so far because I might add a few others, rearrange them and such. It could still use a healthy bit of editing. But I think the bulk of the value of the book is already there.

Value? I think there is! While it’s fun to learn some CSS trickery, I think there is value beyond the tricks themselves. Tricks help you see how CSS works at a deeper level. When you understand the trick, you’re seeing how that part of CSS works through a new lens and it helps you be more in tune with the nature of that CSS. It will help you reach for those CSS properties more intuitively when you know what they are capable of.

In another sense, it’s like taking a walk with weights in your backpack. You do it intentionally so it feels easier to walk when they’re removed. The tricks are like mental weights. They make writing less-tricky CSS feel easier.

So about buying the book. You don’t buy the book directly. What you buy is an MVP Supporter membership to this site. When you’re an MVP Supporter, you have access to the book, and more. This is the whole package:

  • No ads. You see no ads on this site, except for sponsored posts which are just blog posts and I try to make useful anyway.
  • Extra content. You can read the digital books I’m making (including some chapters that are in progress.)
  • Easier commenting. You’ll be logged in, so leaving comments is easier and won’t require the delay for approval.
  • Good feels. And, of course, you get the extreme sense of satisfaction of supporting this site and our commitment to bringing you useful tech knowledge.

It’s just just $20/year.

Have I, or this site, helped you out over the years? This is the best way to say thanks.

Also, if you would really like to have access to read the book, and can’t afford it right now, I totally get it. Email me at and we can work that out.

The post Book: The Greatest CSS Tricks Vol. I appeared first on CSS-Tricks.

Quick Tips for High Contrast Mode

Css Tricks - Fri, 06/26/2020 - 12:30pm

Sarah Higley has some CSS tricks up her sleeve for dealing with High Contrast Mode on Windows, which I learned is referred to as WHCM.

Here’s the first trick:

[…] if the default CSS outline property doesn’t give you the visual effect you want [in WHCM] for focus states, there’s a very simple fix. Instead of overriding default browser focus styles with outline: none, make it transparent instead: outline 3px solid transparent.

That will essentially do nothing outside of WHCM, but in WHCM, it will be a thick white border, which is a strong, good visual focus style.

Direct Link to ArticlePermalink

The post Quick Tips for High Contrast Mode appeared first on CSS-Tricks.

The Return of the 90s Web

Css Tricks - Fri, 06/26/2020 - 9:55am

One of my forever-lessons here on CSS-Tricks is that having your own website and blogging on it is a good idea. It’s probably one of the best decisions I’ve ever made, as it’s been a direct source of fun, career development and, eventually, income.

I always chuckle at little blogging is cool again declarations from the community. It’s always cool, my friends. But it is always nice to see more people pick it back up.

I enjoyed this post from Max Böck that gets into how what is old is new again. Server side rendering! Personal websites! Blogging! Heck yes.

Direct Link to ArticlePermalink

The post The Return of the 90s Web appeared first on CSS-Tricks.

In Defense of a Fussy Website

Css Tricks - Fri, 06/26/2020 - 9:12am

The other day I was doom-scrolling twitter, and I saw a delightful article titled “The Case for Fussy Breakfasts.” I love food and especially breakfast, and since the pandemic hit I’ve been using my breaks in between meetings (or sometimes on meetings, shh) to make a full bacon, poached egg, vegetable plate, so I really got into the article. This small joy of creating a bit of space for myself for the most important meal of the day has been meaningful to me — while everything else feels out of control, indulging in some ceremony has done a tiny part to offset the intensity of our collective situation.

It caused me to think of this “fussiness” as applied to other inconsequential joys. A walk. A bath. What about programming?

While we’re all laser-focused on shipping the newest feature with the hottest software and the best Lighthouse scores, I’ve been missing a bit of the joy on the web. Apps are currently conveying little care for UX, guidance, richness, and — well, for humans trying to communicate through a computer, we’re certainly bending a lot to… the computer.

I’m getting a little tired of the web being seen as a mere document reader, and though I do love me a healthy lighthouse score, some of these point matrixes seem to live and die more by our developer ego in this gamification than actually considering what we can do without incurring much weight. SVGs can be very small while still being impactful. Some effects are tiny bits of CSS. JS animations can be lazy-loaded. You can even dazzle with words, color, and layout if you’re willing to be a bit adventurous, no weight at all!

A few of my favorite developer sites lately have been Josh Comeau, Johnson Ogwuru and Cassie Evans. The small delights and touches, the little a-ha moments, make me STAY. I wander around the site, exploring, learning, feeling actually more connected to each of these humans rather than as if I’m glancing at a PDF of their resume. They flex their muscles, show me the pride they have in building things, and it intrigues me! These small bits are more than the fluff that many portray any “excess” as: they do the job that the web is intending. We are communicating using this tool- the computer- as an extension of ourselves.

Nuance can be challenging. It’s easy as programmers to get stuck in absolutes, and one of these of late has been that if you’re having any bit of fun, any bit of style, that must mean it’s “not useful.” Honestly, I’d make the case that the opposite is true. Emotions attach to the limbic system, making memories easier to recall. If your site is a flat bit of text, how will anyone remember it?

Don’t you want to build the site that teams in companies the world over remember and cite as an inspiration? I’ve been at four different companies where people have mentioned Stripe as a site they would aspire to be like. Stripe took chances. Stripe told stories. Stripe engaged the imagination of developers, spoke directly to us.

I’m sad acknowledging the irony that after thinking about how spot on Stripe was, most of those companies ignored much of what they learned while exploring it. Any creativity, risk, and intention was slowly, piece by piece, chipped away by the drumbeat of “usefulness,” missing the forest for the trees.

When a site is done with care and excitement you can tell. You feel it as you visit, the hum of intention. The craft, the cohesiveness, the attention to detail is obvious. And in turn, you meet them halfway. These are the sites with the low bounce rates, the best engagement metrics, the ones where they get questions like “can I contribute?” No gimmicks needed.

What if you don’t have the time? Of course, we all have to get things over the line. Perhaps a challenge: what small thing can you incorporate that someone might notice? Can you start with a single detail? I didn’t start with a poached egg in my breakfast, one day I made a goofy scrambled one. It went on from there. Can you challenge yourself to learn one small new technique? Can you outsource one graphic? Can you introduce a tiny easter egg? Say something just a little differently from the typical corporate lingo?

If something is meaningful to you, the audience you’ll gather will likely be the folks that find it meaningful, too.

The post In Defense of a Fussy Website appeared first on CSS-Tricks.

Grid for layout, flexbox for components

Css Tricks - Thu, 06/25/2020 - 4:24pm

When should we reach for CSS grid and when should we use flexbox? Rachel Andrew wrote about this very conundrum way back in 2016:

Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.

Ahmad Shadeed wrote a post where he gives the same advice, but from a different angle. He argues we should use grid for layout and flexbox for components:

Remember that old layout method might be perfect for the job. Overusing flexbox or grid can increase the complexity of your CSS by time. I don’t mean they are complex, but using them correctly and in the right context as explained from the examples in this article is much better.

Speaking of which, there’s so many great layout examples in this post, too.

Direct Link to ArticlePermalink

The post Grid for layout, flexbox for components appeared first on CSS-Tricks.

The Mad Magazine Fold-In Effect in CSS

Css Tricks - Thu, 06/25/2020 - 10:13am

This was always my favorite thing in Mad magazine. One page (the inside of the back cover, I think) was covered in a zany illustration. You folded that page in thirds, covering up the middle-third of that image, and a new image would form because the illustration was designed to perfectly line up with those folds. The new image (and text!) was part of the joke.

Every one was a clever trick, so of course, I’m delighted to see that trick make it’s way to CSS, courtesy of Thomas Park.

I’m pretty surprised Thomas was able to do it with a single state (:hover / :active) . I would have bet a nickel that it would have needed @keyframes to adjust the 3D transforms into different positions during the animation, but it looks like multiple transitions happening (both parent and child) handle that.

If you’re in the mood for other cool CSS paper effects…

Here’s a new one from Lynn Fischer:

CodePen Embed Fallback

A classic from Mandy Michael:

CodePen Embed Fallback

And more folding from Mattia Astorino:

CodePen Embed Fallback

Direct Link to ArticlePermalink

The post The Mad Magazine Fold-In Effect in CSS appeared first on CSS-Tricks.

Some Typography Links

Css Tricks - Thu, 06/25/2020 - 9:15am

I just can’t stop opening excellent typography-related articles, which means I need to subject you to blog posts that round them up so I can clean up my open tabs.

Vistaserve is “a grass-roots web hosting initiative hailing from Thornbury, Australia. Inspired by the quirky web of the 90s, we allow users to create home pages, your own little sandbox on the World Wide Web, as it were.” Caitlin & Paul (I think the no-last-name thing is part of the aesthetic) wanted to get the fonts right, which meant removing anti-aliasing (the thing that makes fonts look good on screens!). CSS was no help. Turned out to be quite a journey involving literally rebuilding the fonts.

Thomas Bohm makes the point that the kerning around punctation may require special attention. For example, a question mark needing a little extra space or moving a superscript number away from butting against a letter.

You could do it manually with stuff like &thinsp; or &hairsp in between characters. But I’m far too lazy for that unless I’m working on a very special piece. Personally, I just cross my fingers that the font I’m using is high quality enough to have thought of and implemented this sort of attention to detail.

I’m sure we’ve all seen, “The quick brown fox jumps over the lazy dog” as a tester string for type, because it uses all the characters in the alphabet. Jonathan Hoefler created some new proofing text that is much more helpful for typographers like him.

That’s deep in the type nerd weeds there. More useful perhaps is another recent post from Jonathan on pairings. I’ve probably read dozens of posts on font pairings in my life, but this one resonates the most.

Some of the most dazzling typographic pairings — and certainly my favorites — are those that use unexpected fonts together. At left, the grey flannel suit that is Tungsten Compressed is paired with crimson silk doublet of the St. Augustin Civilité, a fiery sixteenth century typeface that demands a good foil.

If you’ve got macOS Catalina, you’ve got access to some really nice fonts you might not know about that need to be manually downloaded. Ralf Herrmann has the story on what you get:

You can download the fonts right from Font Book

I get Erik Kennedy’s Learn UI Design newsletter, and he mentions using Calena in it…

Overall, Canela walks this balance between the warmth of human handwriting and stately details. It makes me think of something literary, which is why I used it for project in one of the new video lessons in Learn UI Design.

Mark Boulton has a cool new site: TypeSpecimens.

Type specimens are curious objects. They aim to inspire designers. They are tools with which to make design decisions. They are also marketing material for foundries. This project will dig into specimens from these three perspectives: as artefacts made by and for font designers to evolve type culture; as tools for font users to make decisions about choosing and using type; and as effective marketing tools.

The post Some Typography Links appeared first on CSS-Tricks.

The Analytics That Matter

Css Tricks - Thu, 06/25/2020 - 5:00am

I’ve long been skeptical of quoting global browser usage percentages to justify their usage of browser features. It doesn’t matter what global usage of a browser is, other than nerdy cocktail party fodder. The usage that matters is what users on your site are using, and that can be wildly different from site to site.

That idea of tracking real usage of your actual site concept has bounced around my head the last few days. And it’s not just “I can’t use CSS grid because IE 11 has 1.42% of global usage still” stuff, it’s about measuring metrics that matter to your site, no matter what they are.

Performance metrics are a big one. When you’re doing performance testing, much of it is what you would call synthetic testing. An automated browser loads your site and tracks what it finds as it loads, like the timing of a thing, the size of assets, the number of assets, etc. Synthetic information like this enters my mind when spending tons of time on performance. “I bet I can get rid of this one extra request,” I think. “I bet I can optimize this asset a little further.” And the performance tools we use report this kind of data to us readily. How big is our JavaScript bundle? What is our “Largest Contentful Paint”? What is our Lighthouse performance score? All things that are related to performance, but aren’t measuring actual user’s experience.

Let that sit for a second.

There are other analytics we can gather on a site, like usage analytics. For example, we might slap Google Analytics on a site, doing nothing but installing the generic snippet. This is going to tell us stuff like what pages are the most popular, how long people spend on the site, and what countries deliver the most traffic. Those are real user analytics, but it’s very generic analytic information.

If you’re hoping for more useful analytics data on your site, you have to think about it a little harder up front. What do you want to know? Maybe you want to know how often people use Feature X. Or you want to know how many files they have uploaded this week. Or how many messages they have sent. Or how many times they have clicked the star button. This is stuff that tells you how your site is doing. Generic analytics tracking won’t do that; you’ll have to write a little JavaScript to capture and report on those things. It takes a little effort to get the analytics you really care about.

Now apply that to performance tooling.

Rather than generic synthetic tests, why not measure things that are actually important to your specific site? One aspect to this is RUM, that is, “Real User Monitoring.” So rather than a single synthetic test being the source of all performance testing on your site, you’re tracking real users actually using the site on their actual devices. That makes a lot of sense to me, but aside from the logic of it, it unlocks some important data.

For example, one of Google’s Web Core Vitals, which are soon to affect the SEO of our pages, include a metric called First Input Delay (FID) and you have to collect data via JavaScript¹ on your page to use it.

Another Web Core Vital is “Largest Contentful Paint” which is a fascinating attempt at a more meaningful performance metric. Imagine a metric like “start render” or the first page paint. Is that interesting? Sorta. At least it is signaling to the user that something is happening (probably). Yet that first render might not be actually useful content, like the headline and body copy of a news article. So this metric makes a guess at what that useful content probably is and measures that. Very clever.

But, why guess? I get why Google has to guess. They have to measure LCP on a bazillion sites and provide generically useful measurements. But on your own site (again, where the focused analytics actually matter) we can tell performance tools which elements matter us and record when they render. Personally, I’d care about when the article itself renders on this site. With SpeedCurve’s hero rendering time, I could do something like:

<main elementtiming="article"></main> <!-- or focus on the top of the page, like the "hero" timing suggests --> <header elementtiming="hero"></header>

Now I’m measuring what matters to my site and not just generic numbers.

Similarly, FID is cool and all, but why not fire off a JavaScript event telling performance tooling when things happen that are important to your site. For example, on CodePen, we’d do that when the editor is ready to use. That’s called User Timing and it’s a dang W3C spec!

Editors.init(); performance.mark("Editors are initialized.");

These kind some-effort-required analytics are definitely better than the standard fare. Sure, a performance budget that warns you when you go over 200KB of JavaScript is great, but a performance budget that warns you when a core feature of your app isn’t ready until 1.4 seconds when your budget is 1.1 seconds is way more important.

  1. I say this because I was trying to make a chart on the SpeedCurve of the three Web Core Vitals, and you can’t add FID unless you have LUX running, which is their RUM thing. Phew that was a lot of acronyms, sorry.

The post The Analytics That Matter appeared first on CSS-Tricks.

How to Disable Code: The Developer’s Production Kill Switch

Css Tricks - Thu, 06/25/2020 - 4:59am

The following is a guest post written by Carlos Schults.

Being able to disable code in production is a power that many developers aren’t aware of. And that’s a shame. The ability to switch off some portions—or even complete features—of the codebase can dramatically improve the software development process by allowing best practices that can shorten feedback cycles and increase the overall quality.

So, that’s what this post will cover: the mechanisms you can use to perform this switching off, why they’re useful and how to get started. Let’s dig in.

Why Would You Want to Disable Code?

Before we take a deep dive into feature flags, explaining what they are and how they’re implemented, you might be asking: Why would people want to switch off some parts of their codebase? What’s the benefit of doing that?

To answer these questions, we need to go back in time to take a look at how software was developed a couple of decades ago. Time for a history lesson!

The Dark Ages: Integration Hell

Historically, integration has been one of the toughest challenges for teams trying to develop software together. 

Picture several teams inside an organization, working separately for several months, each one developing its own feature. While the teams were working in complete isolation, their versions of the application were evolving in different directions. Now they need to converge again into a single, non conflicting version. This is a Herculean task. 

That’s what “integration hell” means: the struggle to merge versions of the same application that have been allowed to diverge for too long. 

Enter the Solution: Continuous Integration

“If it hurts, do it more often.” What this saying means is that there are problems we postpone solving because doing so is hard. What you often find with these kinds of problems is that solving them more frequently, before they accumulate, is way less painful—or even trivial.

So, how can you make integrations less painful? Integrate more often.

That’s continuous integration (CI) in a nutshell: Have your developers integrate their work with a public shared repository, at the very least once a day. Have a server trigger a build and run the automated test suite every time someone integrates their work. That way, if there are problems, they’re exposed sooner rather than later.

How to Handle Partially Completed Features

One challenge that many teams struggle with in CI is how to deal with features that aren’t complete. If developers are merging their code to the mainline, that means that any developments that take more than one day to complete will have to be split into several parts. 

How can you avoid the customer accessing unfinished functionality? There are some trivial scenarios with similarly trivial solutions, but harder scenarios call for a different approach: the ability to switch off a part of the code completely.

Feature Flags to the Rescue Defining Feature Flags

There are many names for the mechanisms that allow developers to switch a portion of their code off and on. Some call them “feature toggles” or “kill switches.” But “feature flags” is the most popular name, so that’s what we’ll use for the remainder of this post. So, what are feature flags?

Put simply, feature flags are techniques that allow teams to change the behavior of an application without modifying the code. In general, flags are used to prevent users from accessing and using the changes introduced by some piece of code, because they’re not adequate for production yet for a number of reasons.

Disable Code: What Are the Use Cases?

We’ll now cover some of the most common use cases for disabling code in production.

Switching Off Unfinished Features

As you’ve seen, one of the main use cases for feature flags is preventing users from accessing features that aren’t ready for use yet.

That way, programmers developing features that are more complex and take a longer time to complete aren’t prevented from integrating their work often and benefiting from it.

Enabling A/B Testing

The adoption of feature flags enables the use of several valuable practices in the software development process, one of which is A/B testing

A/B testing is a user experience research technique that consists of comparing two versions of a website or application to decide which one to keep. It entails randomly splitting users into two groups, A and B, and then delivering a different version of the application to each group. One group might receive the current production version, which we call the “control,” whereas the second group would receive the candidate for the new version, called the “treatment.” 

The testers then monitor the behavior of both groups and determine which of the versions achieved better results. 

Feature flags are a practical way to enable A/B testing because they allow you to quickly and conveniently change between the control and treatment versions of your application.

Enabling Canary Releases

If you deliver the new version of your app to your entire userbase at once, 100 percent of your users will be impacted if the release is bad in some way. What if you could gradually roll out the new version instead? You’d first deploy to a small subset of users, monitoring that group to detect issues. If something went wrong, you could roll it back. If everything looked fine, you could then gradually release the version for larger groups. That’s a canary release in a nutshell. It’s another powerful technique that feature flags might help with.

Customizing Features According to Users’ Preferences

It’s not uncommon to have to customize your application according to the needs of specific users, and there are several ways in which software teams can accomplish that—some more efficient, and others less so (companies that create separate branches or entire repositories for each client come to mind).

This is another area where feature flags could help, allowing teams to dynamically switch between different versions of the same functionality.

Disable Code in Production 101

How do you go about disabling code? That’s what we’re going to see now, in three increasingly sophisticated phases.

First Stage: The Most Basic Approach

We start with an approach that’s so primitive, it maybe shouldn’t be considered a feature flag at all. Consider the pseudocode below:

calculateAdditionalWorkHours(Employee employee, Date start, Date end) { // return calculateAdditionalWorkHoursSameOldWay(employee, start, end); return calculateAdditionalWorkHoursImproved(employee, start, end); }

In the code above, we’re just commenting out the old version of some method and replacing it with a new version. When we want the older version to be used, we just do the opposite. (Well, I said it was primitive.) This approach lacks one of the most fundamental properties of a feature flag—the ability to change how the application behaves without changing its code.

However, it plants the seed for more sophisticated approaches.

Second Stage: Taking the Decision Out of the Code

The previous approach didn’t allow developers to select the desired version of the feature without changing the code. Fortunately, that’s not so hard to do. First, we introduce a logical variable to determine which version we’re going to use:

calculateAdditionalWorkHours(Employee employee, Date start, Date end) { var result = useNewCalculation ? calculateAdditionalWorkHoursImproved(employee, start, end) : calculateAdditionalWorkHoursSameOldWay(employee, start, end); return result; }

Then, we use some mechanism to be able to assign the value to the variable from an external source. We could use a configuration file:

var useNewCalculation = config[newCalculation];

Passing arguments to the application might be another option. What matters is that we now have the ability to modify how the app behaves from the outside, which is a great step toward “true” feature flagging.

Keep in mind that the code examples you see are all pseudocode. Using your favorite programming language, there’s nothing stopping you from starting with this approach and taking it up a notch. You could, for instance, use classes to represent the features and design patterns (e.g., factories) to avoid if statements.

Stage 3: Full-Fledged Feature Flag Management

The previous approach might be enough when your application has only a small number of flags. But as that number grows, things start to become messy.

First, you have the issue of technical debt. Manually implemented feature flags can create terribly confusing conditional flows in your codebase. That only grows worse with new flags being introduced each day. Additionally, they might make the code harder to understand and navigate, especially for more junior developers, which is an invitation for bugs.

Another problem is that as the number of flags grows, it becomes more and more common to forget to delete old, obsolete ones.

The main problem of a homegrown approach is that it doesn’t give you an easy way to see and manage all of your flags at once. That’s why our third and final stage is a single piece of advice: Instead of rolling out your own feature flags approach, adopt a third-party feature flag management system.

Feature Flags Are a CI/CD Enabler

We’ve covered the mechanisms developers can use to disable portions of their codebase in production without having to touch the code. This capability is powerful and enables techniques such as A/B testing and canary releases, which are all hallmarks of a modern, agile-based software development process.

The names for the techniques might vary—feature flags, feature toggles, feature flipper, and so on. The way in which the techniques are implemented can also vary—from a humble if statement to sophisticated cloud-based solutions.

But no matter what you call them, you can’t overstate the benefit these mechanisms offer. They’re an enabler of Continuous Integration, which is essential for any modern software organization that wants to stay afloat.

The post How to Disable Code: The Developer’s Production Kill Switch appeared first on CSS-Tricks.

Hide Scrollbars During an Animation

Css Tricks - Wed, 06/24/2020 - 11:33am

CSS still can’t animate to auto dimensions.

.dropdown { transition: 0.2s; height: 0; } { /* the height will change, but it won't animate. */ height: auto; }

There is JavaScript trickery you can try. Brandon Smith outlined several techniques here a little while back. My mind always goes to this solution just because it’s so simple:

.dropdown { transition: 0.2s; max-height: 0; } { /* &#x1f389; */ max-height: 400px; }

Now we have this 400px magic number which is really not ideal. But the fact that this works and is so simple makes it extremely appealing that I use it production all the time.

But the magic number isn’t the only problem. Another problem is scrollbars.

When we set max-height: 0;, we also need overflow: hidden; to make sure the dropdown is actually hidden when it is closed. When the dropdown is open, we should probably be using overflow: auto; so that we don’t accidentally cut off content in case the natural height of the dropdown is taller than the max-height after it expands. The use of overflow: auto; solves that problem while introducing another: during the expansion, our dropdown will always have scrollbars for at least part of the expansion, even if the final expansion height doesn’t need them. That’s awkward!

CSS trickery to the rescue.

We can still use overflow: auto; on the expanded state — we’ll just override it during the animation. As we learned in the great CSS specificity battle, @keyframes have an amazing ability to override anything while they are active. Let’s use them not to animate the opening, but just for this scrollbar-hiding functionality:

.dropdown { max-height: 0; overflow: hidden; transition: max-height 1.2s ease-in-out; } { overflow: auto; max-height: 400px; animation: hide-scroll 1.2s backwards; @keyframes hide-scroll { from, to { overflow: hidden; } } }

That does the trick!

CodePen Embed Fallback

Try adjusting the height to something less to see how you don’t see scrollbars during the animation but only at the end when they are needed. That causes a little bit of jerkiness when the scrollbar pops in, but that was acceptable in my case as it’s rare that it happens at all. If you absolutely wanted to stop the jerkiness, you’d probably apply a (custom) scrollbar at all times to the dropdown and perhaps adjust the styling of the scrollbar during the animation, if needed.

Credit here to Mr. Stephen Shaw of the fancy @keyframers for this trick. I yanked him in to help me figure it out while I was working on it for something on CodePen. We decided to turn the trick into a video for the CodePen channel showcasing Collab Mode, which we used to figure out the problem/solution:

The post Hide Scrollbars During an Animation appeared first on CSS-Tricks.

WebP Image Support Coming to iOS 14

Css Tricks - Tue, 06/23/2020 - 1:23pm

Apple announced a ton of new updates at yesterday’s WWDC20 keynote address, from new hardware to updated applications. There’s lots to gawk at and enough device-envy to go around.

But there’s one little line in the Safari 14 Beta release notes that caught my eye:

Added WebP image support.


This excites me because WebP is a super progressive format that encodes images in lossless and lossy formats that we get with other image formats we already use, like JPEG, but at a fraction of the file size. We use WebP right here at CSS-Tricks, thanks to Jetpack and its Site Accelerator feature that serves WebP versions of the images we upload to browsers that support them. Jeremy Wagner has a great write-up on WebP and how to work with it, specifically for WordPress.

So, yes, this means WebP will be largely supported across the board (:IE-sad-trombone:) once Safari 14 ships.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeFirefoxIEEdgeSafari3265No1814Mobile / TabletAndroid ChromeAndroid FirefoxAndroidiOS Safari81684.2-4.314.0

Even with that great support, defining fallbacks with the <picture> element is still a good idea.

<picture> <source srcset="img/cat.webp" type="image/webp"> <source srcset="img/cat.jpg" type="image/jpeg"> <img src="img/cat.jpg" alt="Alt Text!"> </picture>

Oh, and not to be completely overshadowed, Safari 14 also squeezes in some CSS goodies, like the :is() and :where() pseudo class functions, which we linked up a couple of weeks ago. Jen Simmons picked out other key features we should be excited about.

Safari 14 Beta Release Notes
• Added WebP
• Changed to derive <img> aspect ratio from size attributes
• Added :is()
• Added :where()
• Safari no longer supports Flash
• Added Safari Web Extensions
• Added Webpage Translation (Beta)

& much more:

— Jen Simmons (@jensimmons) June 22, 2020

Direct Link to ArticlePermalink

The post WebP Image Support Coming to iOS 14 appeared first on CSS-Tricks.

Linkbait 45

QuirksBlog - Tue, 06/23/2020 - 3:18am

Cleaning up my tabs.

  • So a sponsor asked if there was any performance-centric publication. I did not know, asked around, and found that just about the only one is the perf email newsletter. So just so you know; it’s supposed to be worth the subscription.
    (BTW: we postponed to 2021. This year it’s just not possible to run physical events.)
  • Speaking of events, Benedict Evans wrote an excellent article on the future of events. His experience is more with the huge trade shows than with our focused events, but he makes a few cogent points. Online events are quite different from physical ones (I already figured that out), but nobody yet knows how to do them properly. Instead of doing something truly online, most events just copy physical events while pointing a camera at the speaker and providing. That’s not the way forward. See also the early web that copied print. We slowly learned that it’s something quite different.
    Regardless, Krijn and I are not going to try online events. Instead we’ll wait until we can hold physical ones again; that’s where our strength lies.
    One more excellent point from the article: expensive, or even not-cheap, tickets, as well as organising and paying for your flight and hotel, serves as a selection filter, so that you end up with people who really value physical events.
    There is a lot of pent-up demand for phyiscal events, and that won’t go away, so physical events will return. Still, new forms of online events might also come out of this crisis.
  • A while ago I considered writing an article about the Apple/Google initiative for somewhat-privacy-protecting Covid-tracking, and I gathered some sources. I never wrote the article, but here are the sources anyway:
    • The press release
    • Google’s simple overview
    • Specifications
    • Initial Cnet overview article
    • A rather critical look at the privacy implications. I had the idea the author was too negative, or made some assumption somewhere that was not entirely warranted, but I never actually figured out what sort of problem I felt this article had.
    • A more moderate Wired article that acknowledges possible privacy problems, and gives practical examples, one creepy neighbour and one creepy ad firm, and runs through some other problems as well. As I see it, these problems are inherent to any form of smartphone-based mass surveillance scheme.
    (To be honest, to me contact tracing apps are a sneaky way to avoid the much more expensive contact tracing by actual humans, which I suspect works much better. Also, politicians desperately want to be seen to be tech-literate, so we need an app. Absolutely, positively need an app. I mean, it’s technology, you know ...)
  • A nice line of CSS Grid for you to study. I found out about auto-fill here.
  • Lea takes a look at hybrid positioning (ie. switching from a fixed-like to an absolute-like positioning) in CSS, and as usual I learned a lot here as well. I had this effect on my site since 2004 or so, and I switch from fixed to absolute with JavaScript, because that was the only possibility back then. Meanwhile it turns out you can do this mostly in CSS as well. Also teaches you how to change CSS custom properties in JavaScript.
    I’ve been thinking about it, and I don’t see a way of doing this in pure CSS, because at some point you have to switch from fixed to absolute, and that cannot be done in CSS alone.
  • Speaking of CSS custom properties, Lea’s article and this one taught me that they in fact contain strings that do not have to be valid CSS. It’s only interpreted when it’s actually used in a CSS expression. See also this conversation with Lea and Tab, as well as this article by Jeremy that actually pushed me in to this particular rabbit hole. Thing learned!
  • The Chrome team is preparing to do something about ultra-heavy ads; overview, technical details. Curious what comes of this. Something must be done on the browser side of things to clamp down on online junk; this may be a step in the right direction. Supposed to land somewhere in August.
  • I am probably going to write more about monetization of resources such as this one, or front-end tools, and had a good Twitter conversation (yes! they still exist!) with Scott Wilson in particular. I gathered a few articles, but an incident with my computer made me lose most of them. Here are the two surviving ones:
    • An excellent overview of OSS business models (which I think we should take as a template for web dev monetization)
    • A more critical look at several options. Money quote (pun not intended):

      We should remember that a big part of innovation comes from developers working at organizations adopting open source software [...]. It’s these organizations that should be tasked to sustain open source software [...], especially since they depend on open source software to survive as a business.

  • Very nice online presentation of excerpts from the diaries of captain DaCosta, a 16th century black Portuguese sea captain who ended up in Japan. Contains interesting details. The only thing I’m missing is bibliographical information about the full diary. If it’s translated into a language I can read I might actually pick it up.
  • Have a tip for the next Linkbait? Or a comment on this one? Let me know (or here or here).

An Overview of Scroll Technologies

Css Tricks - Mon, 06/22/2020 - 11:52am

Scroll-related animations have been used on the web for years. In recent years, they’ve started to become more common, perhaps in part due to devices being higher-performing and thus able to handle more animation. 

There are a number of scroll related technologies out there, so this article’s aim is to provide an overview of them and tools to help choose the one that’s right for you. I’d argue that these technologies can be broken down into two broad categories: ones for specific scroll-related behaviors and ones for more generic scroll-related behaviors.

Technologies for specific scroll-related behaviors

There are a few simple native CSS scroll effects that are supported by modern browsers. In some limited use cases they can be sufficient for your scroll animation needs.

position: sticky;

If all you need is for an element to stay in the same place on scroll for a portion of the page, using position: sticky is a good option. It’s straightforward and built into modern browsers. That said, a polyfill is required for IE support and some mobile browsers. For a solid overview, check out this article by Preethi.

CodePen Embed Fallback CSS parallax

This isn’t a technology as much as a technique, but it’s pretty handy for simple parallax effects where you want different pieces of the page to move at different speeds on scroll. There’s a good write up of the technique on and a bunch of examples on CodePen, like this Firewatch header. The biggest downside for me is that it’s difficult to understand what values to use to set the perspective and transforms in order to get the parallax effect exactly right.

CodePen Embed Fallback CSS scroll snap points

Scroll snap points allow the browser to snap to particular scroll positions that you set after a user is done with their normal scrolling. This can be helpful for keeping certain elements in view. However, the API is still in flux so be careful to use the most up to date API and be careful about relying on it in production. This CSS-Tricks article by Max Kohler is a good place to learn about it right now.

CodePen Embed Fallback Smooth scrolling

Smooth scrolling is supported natively when jumping from section to section within a page using window.scrollTo() in JavaScript or even the scroll-behavior property in CSS. Generic smooth scrolling that smooths out mouse wheel actions is not supported natively in all browsers at this time. There are various JavaScript libraries that attempt to add smooth scroll support for the mousewheel action, but I’ve yet to find one that is bug-free and plays nicely with all other scroll technologies. Plus, smooth scrolling isn’t always good in the first place.

Technologies for generic scroll behaviors

Currently, there is no way to create or fire generic animations based on the scroll position using just CSS (though there is a proposal that could support some form of generic scroll based animations in CSS in the distant future) or to scrub through part of an animation. As such, if you want to animate elements on scroll, you’ll need to use at least some JavaScript to create the effect you want. There are two broad methods of using JavaScript to fire animations on scroll: using intersection observers and using the scroll event.


Intersection observers are great if all you need for your animation is information related to whether or not and how much of an element is visible in the viewport. This makes them a good option for reveal animations. Even then, some things are difficult (though not impossible) using intersection observers, such as firing different animations depending on the direction an element enters the viewport. Intersection observers also aren’t very helpful if you want to do any scroll animations when an element is in between and not overlapping with the start and end points. 

Using the scroll event

Using the scroll event will give you the most freedom in controlling animations on scroll. It allows you to affect an element on scroll no matter where it is in terms of the viewport and set up starting and ending points exactly as you need for your project. 

With that being said, it can also be intense on performance if it isn’t throttled correctly and doesn’t have a convenient API to create particular behaviors. This is why it’s oftentimes helpful to use a good scrolling library that can handle the throttling for you and give you a more handy API to work with. Some can even handle a lot of the resizing issues for you!

Tools to create generic scroll behaviors

There are a few holistic scrolling libraries that attempt to give you full control over animations on scroll without you having to perform all of the calculations yourself. 


ScrollMagic provides a relatively simple API to create various effects on scroll and can be hooked into different animation libraries like GSAP and Velocity.js. However, it has become less maintained over the past few years, which lead to the creation of ScrollScene.


ScrollScene is essentially a wrapper to try and make ScrollMagic and/or the intersection observer more usable. It uses a custom, more maintained version of ScrollMagic and adds additional features like video playback, scene init breakpoints, and scene duration breakpoints. It also makes use of GSAP


ScrollTrigger is an official GreenSock plugin for GSAP. It has a long list of features and has the most easy to use API of any scroll library (at least to me). Using it, you can have complete control to define where your scroll animations start and end, animate anything (WebGL, canvas, SVG, DOM, whatever) on scroll, pin elements in place while the animation is running, and more. Plus it has the support of GreenSock and the GreenSock forums

Notable mention: Locomotive Scroll

While it doesn’t attempt to be as comprehensive of a scrolling library as the other libraries mentioned above, Locomotive Scroll is focused on providing custom smooth scrolling. You can also animate certain properties of DOM objects by adding data attributes or hook into the onscroll event to animate other types of objects. 

In summary

For some particular scroll animation effects, like sticky positioning and parallax, CSS technologies may be sufficient, at least when using a polyfill for browsers that don’t support those properties.

I generally recommend using GSAP’s ScrollTrigger because it can do everything that CSS properties can do, plus much more. ScrollTrigger will handle the browser support and calculations so that you can focus on animating!

Here’s a table covering which tools you can use to create particular effects:

ScrollTriggerLocomotive ScrollScrollSceneScrollMagicIntersection observersSmooth ScrollingCSS scroll snap pointsCSS parallaxposition: stickyPinning✅⚪️✅✅❌❌❌❌✅Parallax effects✅✅✅✅❌❌❌✅❌Scrubbing through animation with easing✅⚪️⚪️⚪️⚪️❌❌⚪️❌Snaps scroll position✅⚪️⚪️⚪️⚪️❌✅❌❌Dynamic Batching / Staggering✅❌✅❌✅❌❌❌❌Supports horizontal scroll effects✅✅✅✅✅✅✅✅✅

Here’s a table comparing various other aspects of scroll technology:

ScrollTriggerLocomotive ScrollScrollSceneScrollMagicIntersection observersSmooth scrollingCSS scroll snap pointsCSS parallaxposition: stickyUsable in production (good browser support)✅⚪️✅✅⚪️⚪️⚪️✅⚪️Complete freedom in animation✅⚪️✅✅❌❌❌❌❌Maintained✅✅✅❌n/an/an/an/an/aWorks with DOM, Canvas, WebGl, SVG✅⚪️✅✅✅❌❌❌❌Works easily with resizing✅✅✅⚪️✅✅✅✅✅Restricts animation to relevant section✅❌⚪️⚪️✅✅✅❌✅Directionally aware✅⚪️✅✅⚪️❌❌❌❌Native technology❌❌❌❌✅✅✅✅✅✅ = Yes
⚪️ = Partial support
❌ = No

The post An Overview of Scroll Technologies appeared first on CSS-Tricks.

Rough Notation

Css Tricks - Mon, 06/22/2020 - 11:51am

This is a neat little library. It uses SVG to insert hand-drawn looking annotations to elements (probably text), like underlines and box highlights (there are 6 design options, all configurable). Super clever.

Here’s a little demo:

CodePen Embed Fallback

Aside from it just being cool, I really like how it was released. You can use it from npm. It’s ready to be used via ES6 imports. You can just use it as a <script src>. Then, if you happen to be using a JavaScript framework, there are wrappers for React, Vue, Svelte, Angular, and Web Components. Nice.

Not all projects take that approach. Here’s another very cool project: gooey-react. It takes the gooey effect concept and essentially gives it an API via React/JSX.

Again, this is very cool and clever and I love it — but imagine another approach instead, perhaps an HTML wrapper with data-* attributes to control the effect. With that, wrappers could be (easily?) made in any JavaScript framework.

Direct Link to ArticlePermalink

The post Rough Notation appeared first on CSS-Tricks.

Using Custom Property “Stacks” to Tame the Cascade

Css Tricks - Mon, 06/22/2020 - 4:47am

Since the inception of CSS in 1994, the cascade and inheritance have defined how we design on the web. Both are powerful features but, as authors, we’ve had very little control over how they interact. Selector specificity and source order provide some minimal “layering” control, without a lot of nuance — and inheritance requires an unbroken lineage. Now, CSS Custom Properties allow us to manage and control both cascade and inheritance in new ways.

I want to show you how I’ve used Custom Property “stacks” to solve some of the common issues people face in the cascade: from scoped component styles, to more explicit layering of intents.

A quick intro to Custom Properties

The same way browsers have defined new properties using a vendor prefix like -webkit- or -moz-, we can define our own Custom Properties with an “empty” -- prefix. Like variables in Sass or JavaScript, we can use them to name, store, and retrieve values — but like other properties in CSS, they cascade and inherit with the DOM.

/* Define a custom property */ html { --brand-color: rebeccapurple; }

In order to access those captured values, we use the var() function. It has two parts: first the name of our custom property, and then a fallback in case that property is undefined:

button { /* use the --brand-color if available, or fall back to deeppink */ background: var(--brand-color, deeppink); }

This is not a support fallback for old browsers. If a browser doesn’t understand custom properties, it will ignore the entire var() declaration. Instead, this is a built-in way of handling undefined variables, similar to a font stack defining fallback font families when one is unavailable. If we don’t provide a fallback, the default is unset.

Building variable “stacks”

This ability to define a fallback is similar to “font stacks” used on the font-family property. If the first family is unavailable, the second will be used, and so on. The var() function only accepts a single fallback, but we can nest var() functions to create custom-property fallback “stacks” of any size:

button { /* try Consolas, then Menlo, then Monaco, and finally monospace */ font-family: Consolas, Menlo, Monaco, monospace; /* try --state, then --button-color, then --brand-color, and finally deeppink */ background: var(--state, var(--button-color, var(--brand-color, deeppink))); }

If that nested syntax for stacked properties looks bulky, you can use a pre-processor like Sass to make it more compact.

CodePen Embed Fallback

That single-fallback limitation is required to support fallbacks with a comma inside them — like font stacks or layered background images:

html { /* The fallback value is "Helvetica, Arial, sans-serif" */ font-family: var(--my-font, Helvetica, Arial, sans-serif); } Defining “scope”

CSS selectors allow us to drill down into the HTML DOM tree, and style elements anywhere on the page, or elements in a particular nested context.

/* all links */ a { color: slateblue; } /* only links inside a section */ section a { color: rebeccapurple; } /* only links inside an article */ article a { color: deeppink; }

That’s useful, but it doesn’t capture the reality of “modular” object-oriented or component-driven styles. We might have multiple articles and asides, nested in various configurations. We need a way to clarify which context, or scope, should take precedence when they overlap.

Proximity scopes

Let’s say we have a .light theme and a .dark theme. We can use those classes on the root <html> element to define a page-wide default, but we can also apply them to specific components, nested in various ways:

CodePen Embed Fallback

Each time we apply one of our color-mode classes, the background and color properties are reset, then inherited by nested headings and paragraphs. In our main context, colors inherit from the .light class, while the nested heading and paragraph inherit from the .dark class. Inheritance is based on direct lineage, so the nearest ancestor with a defined value will take precedence. We call that proximity.

Proximity matters for inheritance, but it has no impact on selectors, which rely on specificity. That becomes a problem if we want to style something inside the dark or light containers.

Here I’ve attempted to define both light and dark button variants. Light mode buttons should be rebeccapurple with white text so they stand out, and dark mode buttons should be plum with black text. We’re selecting the buttons directly based on a light and dark context, but it doesn’t work:

CodePen Embed Fallback

Some of the buttons are in both contexts, with both .light and .dark ancestors. What we want in that case is for the closest theme to take over (inheritance proximity behavior), but what we get instead is the second selector overriding the first (cascade behavior). Since the two selectors have the same specificity, source order determines the winner.

Custom Properties and proximity

What we need here is a way to inherit these properties from the theme, but only apply them to specific children. Custom Properties make that possible! We can define values on the light and dark containers, while only using their inherited values on nested elements, like our buttons.

We’ll start by setting up the buttons to use custom properties, with a fallback “default” value, in case those properties are undefined:

button { background: var(--btn-color, rebeccapurple); color: var(--btn-contrast, white); }

Now we can set those values based on context, and they will scope to the appropriate ancestor based on proximity and inheritance:

.dark { --btn-color: plum; --btn-contrast: black; } .light { --btn-color: rebeccapurple; --btn-contrast: white; }

As an added bonus, we’re using less code overall, and one unified button definition:

CodePen Embed Fallback

I think of this as creating an API of available parameters for the button component. Sara Soueidan and Lea Verou have both covered this well in recent articles.

Component ownership

Sometimes proximity isn’t enough to define scope. When JavaScript frameworks generate “scoped styles” they are establishing specific object-element ownership. A “tab layout” component owns the tabs themselves, but not the content behind each tab. This is also what the BEM convention attempts to capture in complex .block__element class names.

Nicole Sullivan coined the term “donut scope” to talk about this problem back in 2011. While I’m sure she has more recent thoughts on the issue, the fundamental problem hasn’t changed. Selectors and specificity are great for describing how we build detailed styles over top of broad patterns, but they don’t convey a clear sense of ownership.

We can use custom property stacks to help solve this problem. We’ll start by creating “global” properties on the <html> element that are for our default colors:

html { --background--global: white; --color--global: black; --btn-color--global: rebeccapurple; --btn-contrast--global: white; }

That default global theme is now available anywhere we want to refer to it. We’ll do that with a data-theme attribute that applies our foreground and background colors. We want the global values to provide a default fallback, but we also want the option to override with a specific theme. That’s where “stacks” come in:

[data-theme] { /* If there's no component value, use the global value */ background: var(--background--component, var(--background--global)); color: var(--color--component, var(--color--global)); }

Now we can define an inverted component by setting the *--component properties as a reverse of the global properties:

[data-theme='invert'] { --background--component: var(--color--global); --color--component: var(--background--global); }

But we don’t want those settings to inherit beyond the donut of ownership, so we reset those values to initial (undefined) on every theme. We’ll want to do this at a lower specificity, or earlier in the source order, so it provides a default that each theme can override:

[data-theme] { --background--component: initial; --color--component: initial; }

The initial keyword has a special meaning when used on custom properties, reverting them to a Guaranteed-Invalid state. That means rather than being passed along to set background: initial or color: initial, the custom property becomes undefined, and we fallback to the next value in our stack, the global settings.

We can do the same thing with our buttons, and then make sure to apply data-theme to each component. If no specific theme is given, each component will default to the global theme:

CodePen Embed Fallback Defining “origins”

The CSS cascade is a series of filtering layers used to determine what value should take precedence when multiple values are defined on the same property. We most often interact with the specificity layers, or the final layering based on source-order — but the first layer of cascade is the “origin” of a style. The origin describes where a style came from — often the browser (defaults), the user (preferences), or the author (that’s us).

By default, author styles override user preferences, which override browser defaults. That changes when anyone applies `!important` to a style, and the origins reverse: browser `!important` styles have the highest origin, then important user preferences, then our author important styles, above all the normal layers. There are a few additional origins, but we won’t go into them here.

When we create custom property “stacks,” we’re building a very similar behavior. If we wanted to represent existing origins as a stack of custom properties, it would look something like this:

.origins-as-custom-properties { color: var(--browser-important, var(--user-important, var(--author-important, var(--author, var(--user, var(--browser)))))); }

Those layers already exist, so there’s no reason to recreate them. But we’re doing something very similar when we layer our “global” and “component” styles above — creating a “component” origin layer that overrides our “global” layer. That same approach can be used to solve various layering issues in CSS, which can’t always be described by specificity:

  • Override » Component » Theme » Default
  • Theme » Design system or framework
  • State » Type » Default

Let’s look at some buttons again. We’ll need a default button style, a disabled state, and various button “types,” like danger, primary and secondary. We wan’t the disabled state to always override the type variations, but selectors don’t capture that distinction:

CodePen Embed Fallback

But we can define a stack that provides both “type” and “state” layers in the order that we want them prioritized:

button { background: var(--btn-state, var(--btn-type, var(--btn-default))); }

Now when we set both variables, the state will always take precedence:

CodePen Embed Fallback

I’ve used this technique to create a Cascading Colors framework that allows custom theming based on layering:

  • Pre-defined theme attributes in the HTML
  • User color preferences
  • Light and dark modes
  • Global theme defaults
Mix and match

These approaches can be taken to an extreme, but most day-to-day use-cases can be handled with two or three values in a stack, often using a combination of the techniques above:

  • A variable stack to define the layers
  • Inheritance to set them based on proximity and scope
  • Careful application of the `initial` value to remove nested elements from a scope

We’ve been using these custom property “stacks” on our projects at OddBird. We’re still discovering as we go, but they’ve already been helpful in solving problems that were difficult using only selectors and specificity. With custom properties, we don’t have to fight the cascade or inheritance. We can capture and leverage them, as-intended, with more control over how they should apply in each instance. To me, that’s a big win for CSS — especially when developing style frameworks, tools, and systems.

The post Using Custom Property “Stacks” to Tame the Cascade appeared first on CSS-Tricks.


Css Tricks - Sat, 06/20/2020 - 3:50am

I remember searching for tutorials for making seamless patterns in Photoshop¹ all the time back in the day.

It’s fun to see this little website for building repeating patterns as its one job. It does everything you’d expect: pick a background, drag some decorations onto it and position them (overlapping an edge is fine, which is the hard part, and makes the designs look less griddy), color them, and away you go.

  1. The trick is to make a square with a design in it, then Filter > Other > Offset of half the width/height to make the seamless repeating edges work, then add a bit more in gaps.

Direct Link to ArticlePermalink

The post Patternico appeared first on CSS-Tricks.

Just another +1 for subgrid

Css Tricks - Fri, 06/19/2020 - 4:30am

I’d say 85% of my grid usage is in one of these two categories…

  1. I just need some pretty basic (probably equal width) columns that ends up being something like like grid-template-columns: repeat(3, minmax(0, 1fr)); to be safe.
  2. Actually doing some real layout where five minutes in I realize I’d really like subgrid.

Subgrid? It’s a nice intuitive way to have a child element on the grid inherit relevant grid lines from the parent grid.

Here’s a great recent video from Rachel Andrew covering it. Last year, we linked up her talk on the same! It’s such a clutch feature and I wish we could rely on it cross-browser. Right now, Firefox is the only one that has it. (Chrome issue, Safari issue)

In my recent video, right about at 20 minutes, I realize subgrid would make even a fairly simple layout much nicer, like removing the need for variables or resorting to magic numbers.

The post Just another +1 for subgrid appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.