Month: October 2022

The New CSS Media Query Range Syntax

We rely on CSS Media Queries for selecting and styling elements based on a targeted condition. That condition can be all kinds of things but typically fall into two camps: (1) the type of media that’s being used, and (2) a specific feature of the browser, device, or even the user’s environment.

So, say we want to apply certain CSS styling to a printed document:

@media print {   .element {     /* Style away! */   } }

The fact that we can apply styles at a certain viewport width has made CSS Media Queries a core ingredient of responsive web design since Ethan Marcotte coined the term. If the browser’s viewport width is a certain size, then apply a set of style rules, which allows us to design elements that respond to the size of the browser.

/* When the viewport width is at least 30em... */ @media screen and (min-width: 30em) {   .element {     /* Style away! */   } }

Notice the and in there? That’s an operator that allows us to combine statements. In that example, we combined a condition that the media type is a screen and that it’s min-width feature is set to 30em (or above). We can do the same thing to target a range of viewport sizes:

/* When the viewport width is between 30em - 80em */ @media screen and (min-width: 30em) and (max-width: 80em) {   .element {     /* Style away! */   } }

Now those styles apply to an explicit range of viewport widths rather than a single width!

But the Media Queries Level 4 specification has introduced a new syntax for targeting a range of viewport widths using common mathematical comparison operators — things like <, >, and = — that make more sense syntactically while writing less code.

Let’s dig into how that works.

New comparison operators

That last example is a good illustration of how we’ve sort of “faked” ranges by combining conditions using the and operator. The big change in the Media Queries Level 4 specification is that we have new operators that compare values rather than combining them:

  • < evaluates if a value is less than another value
  • > evaluates if a value is greater than another value
  • = evaluates if a value is equal to another value
  • <= evaluates if a value is less than or equal to another value
  • >= evaluates if a value is greater than or equal to another value

Here’s how we might’ve written a media query that applies styles if the browser is 600px wide or greater:

@media (min-width: 600px) {   .element {     /* Style away! */   } }

Here’s how it looks to write the same thing using a comparison operator:

@media (width >= 600px) {   .element {     /* Style away! */   } }

Targeting a range of viewport widths

Often when we write CSS Media Queries, we’re creating what’s called a breakpoint — a condition where the design “breaks” and a set of styles are applied to fix it. A design can have a bunch of breakpoints! And they’re usually based on the viewport being between two widths: where the breakpoint starts and where the breakpoint ends.

Here’s how we’ve done that using the and operator to combine the two breakpoint values:

/* When the browser is between 400px - 1000px */ @media (min-width: 400px) and (max-width: 1000px) {   /* etc. */ }

You start to get a good sense of how much shorter and easier it is to write a media query when we ditch the Boolean and operator in favor of the new range comparison syntax:

@media (400px <= width <= 1000px) {   /* etc. */ }

Much easier, right? And it’s clear exactly what this media query is doing.

Browser support

This improved media query syntax is still in its early days at the time of this writing and not as widely supported at the moment as the approach that combines min-width and max-width. We’re getting close, though! Safari is the only major holdout at this point, but there is an open ticket for it that you can follow.

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


Chrome Firefox IE Edge Safari
104 63 No 104 No

Mobile / Tablet

Android Chrome Android Firefox Android iOS Safari
106 106 106 No

Let’s look at an example

Here’s a layout for that’s nicely suited for larger screens, like a desktop:

A desktop layout with a logo and menu up top, a large heading in white, and an image of a silhouetted person underneath the heading, followed by a footer.

This layout has base styles that are common to all breakpoints. But as the screen gets narrower, we start to apply styles that are conditionally applied at different smaller breakpoints that are ideally suited for tablets all the way down to mobile phones:

Side-by-side screenshots of the mobile and tablet layouts with their CSS Grid tracks overlaid.

To see what’s happening, here’s a how the layout responds between the two smaller breakpoints. The hidden nav list getting displayed as well as title in the main gets increased in font-size.

That change is triggered when the viewport’s changes go from matching one media’s conditions to another:

/* Base styles (any screen size) */ header {   display: flex;   justify-content: center; }  header ul {   display: none; }  .title p {   font-size: 3.75rem; }  /* When the media type is a screen with a width greater or equal to 768px */ @media screen and (width >= 768px) {   header {     justify-content: space-between;   }    header ul {     display: flex;     justify-content: space-between;     gap: 3rem;   }    .title p {     font-size: 5.75rem;   } }

We’ve combined a few of the concepts we’ve covered! We’re targeting devices with a screen media type, evaluating whether the viewport width is greater than or equal to a specific value using the new media feature range syntax, and combining the two conditions with the and operator.

Diagram of the media query syntax, detailing the media type, operator, and range media feature.

OK, so that’s great for mobile devices below 768px and for other devices equal to or greater than 768px. But what about that desktop layout… how do we get there?

As far as the layout goes:

  • The main element becomes a 12-column grid.
  • A button is displayed on the image.
  • The size of the .title element’s font increases and overlaps the image.

Assuming we’ve done our homework and determined exactly where those changes should take place, we can apply those styles when the viewport matches the width condition for that breakpoint. We’re going to say that breakpoint is at 1000px:

/* When the media type is a screen with a width greater or equal to 1000px  */ @media screen and (width >= 1000px) {   /* Becomes a 12-column grid */   main {     display: grid;     grid-template-columns: repeat(12, 1fr);     grid-template-rows: auto 250px;   }    /* Places the .title on the grid */   .title {     grid-row: 1;   }    /* Bumps up the font-size */   .title p {     font-size: 7.75rem;   }    /* Places .images on the grid */   .images {     grid-row: 1 / span 2;     align-self: end;     position: relative;   }    /* Displays the button */   .images .button {     display: block;     position: absolute;     inset-block-end: 5rem;     inset-inline-end: -1rem;   } }
Showing the CSS grid tracks for a desktop layout using a CSS media query with the new range syntax.

Have a play with it:

Why the new syntax is easier to understand

The bottom line: it’s easier to distinguish a comparison operator (e.g. width >= 320px) than it is to tell the difference between min-width and max-width using the and operator. By removing the nuance between min- and max-, we have one single width parameter to work with and the operators tell us the rest.

Beyond the visual differences of those syntaxes, they are also doing slightly different things. Using min- and max- is equivalent to using mathematical comparison operators:

  • max-width is equivalent to the <= operator (e.g. (max-width: 320px) is the same as (width <= 320px)).
  • min-width is equivalent to the >= operator (e.g. (min-width: 320px) is the same as (width >= 320px)).

Notice that neither is the equivalent of the > or < operators.

Let’s pull an example straight from the Media Queries Level 4 specification where we define different styles based on a breakpoint at 320px in the viewport width using min-width and max-width:

@media (max-width: 320px) { /* styles for viewports <= 320px */ } @media (min-width: 320px) { /* styles for viewports >= 320px */ }

Both media queries match a condition when the viewport width is equal to 320px. That’s not exactly what we want. We want either one of those conditions rather than both at the same time. To avoid that implicit changes, we might add a pixel to the query based on min-width:

@media (max-width: 320px){ /* styles for viewports <= 320px */ } @media (min-width: 321px){ /* styles for viewports >= 321px */ }

While this ensures that the two sets of styles don’t apply simultaneously when the viewport width is 320px, any viewport width that fall between 320px and 321px will result in a super small zone where none of the styles in either query are applied — a weird “flash of unstyled content” situation.

One solution is to increase the second comparison scale value (numbers after the decimal point) to 320.01px:

@media (max-width: 320px) { /* styles for viewports <= 320px */ } @media (min-width: 320.01px) { /* styles for viewports >= 320.01px */ }

But that’s getting silly and overly complicated. That’s why the new media feature range syntax is a more appropriate approach:

@media (width <= 320px) { /* styles for viewports <= 320px */ } @media (width > 320px) { /* styles for viewports > 320px */ }

Wrapping up

Phew, we covered a lot of ground on the new syntax for targeting viewport width ranges in CSS Media Queries. Now that the Media Queries Level 4 specification has introduced the syntax and it’s been adopted in Firefox and Chromium browsers, we’re getting close to being able to use the new comparison operators and combining them with other range media features besides width, like height and aspect-ratio

And that’s just one of the newer features that the Level 4 specification introduced, alongside a bunch of queries we can make based on user preferences. It doesn’t end there! Check out the Complete Guide to CSS Media Queries for a sneak peek of what might be included in Media Queries Level 5.

The New CSS Media Query Range Syntax originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


, , ,

Tips for Selecting the Best Software for Beginning Graphic Designers


Fancy Image Decorations: Outlines and Complex Animations

We’ve spent the last two articles in this three-part series playing with gradients to make really neat image decorations using nothing but the <img> element. In this third and final piece, we are going to explore more techniques using the CSS outline property. That might sound odd because we generally use outline to draw a simple line around an element — sorta like border but it can only draw all four sides at once and is not part of the Box Model.

We can do more with it, though, and that’s what I want to experiment with in this article.

Fancy Image Decorations series

Let’s start with our first example — an overlay that disappears on hover with a cool animation:

We could accomplish this by adding an extra element over the image, but that’s what we’re challenging ourselves not to do in this series. Instead, we can reach for the CSS outline property and leverage that it can have a negative offset and is able to overlap its element.

img {   --s: 250px; /* the size of the image */   --b: 8px;   /* the border thickness*/   --g: 14px;  /* the gap */   --c: #4ECDC4;    width: var(--s);   aspect-ratio: 1;   outline: calc(var(--s) / 2) solid #0009;   outline-offset: calc(var(--s) / -2);   cursor: pointer;   transition: 0.3s; } img:hover {   outline: var(--b) solid var(--c);   outline-offset: var(--g); }

The trick is to create an outline that’s as thick as half the image size, then offset it by half the image size with a negative value. Add in some semi-transparency with the color and we have our overlay!

Diagram showing the size of the outline sround the image and how it covers the image on hover.

The rest is what happens on :hover. We update the outline and the transition between both outlines creates the cool hover effect. The same technique can also be used to create a fading effect where we don’t move the outline but make it transparent.

Instead of using half the image size in this one, I am using a very big outline thickness value (100vmax) while applying a CSS mask. With this, there’s no longer a need to know the image size — it trick works at all sizes!

Diagram showing how adding a mask clips the extra outline around the image.

You may face issues using 100vmax as a big value in Safari. If it’s the case, consider the previous trick where you replace the 100vmax with half the image size.

We can take things even further! For example, instead of simply clipping the extra outline, we can create shapes and apply a fancy reveal animation.

Cool right? The outline is what creates the yellow overlay. The clip-path clips the extra outline to get the star shape. Then, on hover, we make the color transparent.

Oh, you want hearts instead? We can certainly do that!

Imagine all the possible combinations we can create. All we have to do is to draw a shape with a CSS mask and/or clip-path and combine it with the outline trick. One solution, infinite possibilities!

And, yes, we can definitely animate this as well. Let’s not forget that clip-path is animatable and mask relies on gradients — something we covered in super great detail in the first two articles of this series.

I know, the animation is a bit glitchy. This is more of a demo to illustrate the idea rather than the “final product” to be used in a production site. We’d wanna optimize things for a more natural transition.

Here is a demo that uses mask instead. It’s the one I teased you with at the end of the last article:

Did you know that the outline property was capable of so much awesomeness? Add it to your toolbox for fancy image decorations!

Combine all the things!

Now that we have learned many tricks using gradients, masks, clipping, and outline, it’s time for the grand finale. Let’s cap off this series by combine all that we have learned the past few weeks to showcase not only the techniques, but demonstrate just how flexible and modular these approaches are.

If you were seeing these demos for the first time, you might assume that there’s a bunch of extra divs wrappers and pseudo-elements being used to pull them off. But everything is happening directly on the <img> element. It’s the only selector we need to get these advanced shapes and effects!

Wrapping up

Well, geez, thanks for hanging out with me in this three-part series the past few weeks. We explored a slew of different techniques that turn simple images into something eye-catching and interactive. Will you use everything we covered? Certainly not! But my hope is that this has been a good exercise for you to dig into advanced uses of CSS features, like gradients, mask, clip-path, and outline.

And we did everything with just one <img> element! No extra div wrappers and pseudo-elements. Sure, it’s a constraint we put on ourselves, but it also pushed us to explore CSS and try to find innovative solutions to common use cases. So, before pumping extra markup into your HTML, think about whether CSS is already capable of handling the task.

Fancy Image Decorations series

Fancy Image Decorations: Outlines and Complex Animations originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


, , , , ,

30 Free Elegant Business Card Templates in PSD


30 Free Multipurpose Newspaper Templates in Google Docs


Holographic Trading Card Effect

Simon Goellner (@simeydotme)’s collection of Holographic Trading Cards have captured our attention.

Under the hood there is a suite of filter(), background-blend-mode(), mix-blend-mode(), and clip-path() combinations that have been painstakingly tweaked to reach the desired effect. I ended up using a little img { visibility: hidden; } in DevTools to get a better sense of each type of holographic effect.

Josh Dance (@JoshDance) replied with a breakdown of the effects that lets you manually control the inputs.

To Shared LinkPermalink on CSS-Tricks

Holographic Trading Card Effect originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


, , ,

Creating Animated, Clickable Cards With the :has() Relational Pseudo Class

The CSS :has() pseudo class is rolling out in many browsers with Chrome and Safari already fully supporting it. It’s often referred to it as “the parent selector” — as in, we can select style a parent element from a child selector — but there is so much more that :has() can help us solve. One of those things is re-inventing the clickable card pattern many of us love to use from time to time.

We’ll take a look at how :has() can help us handle linked cards, but first…

What is this :has() pseudo class?

There is already a bunch of great posts floating around that do an excellent job explaining what :has() is and what it’s used for, but it’s still new enough that we ought to say a few words about it here as well.

:has() is a relational pseudo class that’s part of the W3C Selectors Level 4 working draft. That’s what the parentheses are all about: matching elements that are related to — or, more accurately, contain — certain child elements.

/* Matches an article element that contains an image element */ article:has(img) { }  /* Matches an article element with an image contained immediately within it */ article:has(> img) { }

So, you can see why we might want to call it a “parent” selector. But we can also combine it with other functional pseudo classes to get more specific. Say we want to style articles that do not contain any images. We can combine the relational powers of :has() with the negation powers of :not() to do that:

/* Matches an article without images  */ article:has(:not(img)) { }

But that’s just the start of how we can combine powers to do more with :has(). Before we turn specifically to solving the clickable card conundrum, let’s look at a few ways we currently approach them without using :has().

How we currently handle clickable cards

There are three main approaches on how people create a fully clickable card these days and to fully understand the power of this pseudo class, it’s nice to have a bit of a round-up.

This approach is something used quite frequently. I never use this approach but I created a quick demo to demonstrate it:

There are a lot of concerns here, especially when it comes to accessibility. When users navigate your website using the rotor function, they will hear the full text inside of that <a> element — the heading, the text, and the link. Someone might not want to sit through all that. We can do better. Since HTML5, we can nest block elements inside of an <a> element. But it never feels right to me, especially for this reason.


  • Quick to implement
  • Semantically correct


  • Accessibility concerns
  • Text not selectable
  • A lot of hassle to overwrite styles that you used on your default links

The JavaScript method

Using JavaScript, we can attach a link to our card instead of writing it in the markup. I found this great CodePen demo by costdev who also made the card text selectable in the process:

This approach has a lot of benefits. Our links are accessible on focus and we can even select text. But there are some drawbacks when it comes to styling. If we want to animate those cards, for example, we would have to add :hover styles on our main .card wrapper instead of the link itself. We also would not benefit from the animations when the links are in focus from keyboard tabbing.


  • Can be made perfectly accessible
  • Ability to select text


  • Requires JavaScript
  • Right clicking not possible (although could be fixed with some extra scripting)
  • Will require a lot of styling on the card itself which would not work when focussing the link

The ::after selector approach

This method requires us to set the card with relative positioning, then set absolute positioning on the link’s ::after pseudo selector of a link. This doesn’t require any JavaScript and is pretty easy to implement:

There are a few drawbacks here, especially when it comes to selecting text. Unless you provide a higher z-index on your card-body, you won’t be able to select text but if you do, be warned that clicking the text will not activate your link. Whether or not you want selectable text is up to you. I think it can be a UX issue, but it depends on the use-case. The text is still accessible to screen readers but my main problem with the method is the lack of animation possibilities.


  • Easy to implement
  • Accessible link without bloated text
  • Works on hover and focus


  • Text is not selectable
  • You can only animate the link as this is the element you’re hovering.

A new approach: Using ::after with :has()

Now that we’ve established the existing approaches for clickable cards, I want to show how introducing :has() to the mix solves most of those shortcomings.

In fact, let’s base this approach on the last one we looked at using ::after on the link element. We can actually use :has() there to overcome that approach’s animation constraints.

Let’s start with the markup:

<div class="card">   <img src="cat.webp" alt="Fluffy gray and white tabby kitten snuggled up in a ball." />   <div clas="article-body">     <h2>Some Heading</h2>     <p>Curabitur convallis ac quam vitae laoreet. Nulla mauris ante, euismod sed lacus sit amet, congue bibendum eros. Etiam mattis lobortis porta. Vestibulum ultrices iaculis enim imperdiet egestas.</p>   </div> </div>

I will be keeping things as simple as possible by targeting elements in the CSS instead of classes.

For this demo, we’re going to add an image zoom and shadow to the card on hover, and animate the link with an arrow popping up and while changing the link’s text color. To make this easy, we’re going to add some custom properties scoped on our card. Here’s the basic styling:

/* The card element */ article {   --img-scale: 1.001;   --title-color: black;   --link-icon-translate: -20px;   --link-icon-opacity: 0;    position: relative;   border-radius: 16px;   box-shadow: none;   background: #fff;   transform-origin: center;   transition: all 0.4s ease-in-out;   overflow: hidden; } /* The link's ::after pseudo */ article a::after {   content: "";   position: absolute;   inset-block: 0;   inset-inline: 0;   cursor: pointer; }

Great! We added an initial scale for the image (--img-scale: 1.001), the initial color of the card heading (--title-color: black) and some extra properties we will use to make our arrow pop out of the link. We’ve also set an empty state of the box-shadow declaration in order to animate it later . This sets up what we need for the clickable card right now, so let’s add some resets and styling to it by adding those custom properties to the elements we want to animate:

article h2 {   margin: 0 0 18px 0;   font-family: "Bebas Neue", cursive;   font-size: 1.9rem;   letter-spacing: 0.06em;   color: var(--title-color);   transition: color 0.3s ease-out; } article figure {   margin: 0;   padding: 0;   aspect-ratio: 16 / 9;   overflow: hidden; } article img {   max-width: 100%;   transform-origin: center;   transform: scale(var(--img-scale));   transition: transform 0.4s ease-in-out; } article a {   display: inline-flex;   align-items: center;   text-decoration: none;   color: #28666e; } article a:focus {   outline: 1px dotted #28666e; } article a .icon {   min-width: 24px;   width: 24px;   height: 24px;   margin-left: 5px;   transform: translateX(var(--link-icon-translate));   opacity: var(--link-icon-opacity);   transition: all 0.3s; }  .article-body {   padding: 24px; }

Let’s be kind to people and also add a screen reader class hidden behind the link:

.sr-only:not(:focus):not(:active) {   clip: rect(0 0 0 0);    clip-path: inset(50%);   height: 1px;   overflow: hidden;   position: absolute;   white-space: nowrap;    width: 1px; }

Our card is starting to look pretty sweet. It’s time to add a bit of magic to it. With the :has() pseudo class, we can now check if our link is hovered or focused, then update our custom properties and add a box-shadow. With this little chunk of CSS our card really comes to life:

/* Matches an article element that contains a hover or focus state */ article:has(:hover, :focus) {   --img-scale: 1.1;   --title-color: #28666e;   --link-icon-translate: 0;   --link-icon-opacity: 1;    box-shadow: rgba(0, 0, 0, 0.16) 0px 10px 36px 0px, rgba(0, 0, 0, 0.06) 0px 0px 0px 1px; }

See what’s up there? Now we get the updated styles if any child element in the card is hovered or focused. And even though the link element is the only thing that can contain a hover or focus state in the ::after clickable card approach, we can use that to match the parent element and apply the transitions.

And there you have it. Just another powerful use case for the :has() selector. Not only can we match a parent element by declaring other elements as arguments, but we can match also use pseudos to match and style parents as well.


  • Accessible
  • Animatable
  • No JavaScript needed
  • Uses :hover on the correct element


  • Text is not easily selectable.
  • Browser support is limited to Chrome and Safari (it’s supported in Firefox behind a flag).

Here is a demo using this technique. You might notice an extra wrapper around the card, but that’s just me playing around with container queries, which is just one of those other fantastic things rolling out in all major browsers.

Got some other examples you wish to share? Other solutions or ideas are more than welcome in the comment section.

Creating Animated, Clickable Cards With the :has() Relational Pseudo Class originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.


, , , , , ,

Feather Buildings: A Look At AI-Generated Architecture


The 7 Most Common UX Design Mistakes


Is There Too Much CSS Now?

As front-end developers, we’ve wished for a lot of things over the years — ways to center things in CSS, encapsulate styles, set an element’s aspect ratio, get finer-grained control over our colors, select an element based on its children’s properties, manage layers of specificity, allow elements to respond to the width of their parents… the list goes on and on.

And now that we got all we wished for and more, some of us are asking — do we now have too much CSS?

The dark times

If you, like me, came up in web development during CSS’s infancy, the idea of having too much of it seems ludicrous.

Back in the days, virtually the entire job description of a front-end developer consisted of dealing with CSS’s limitations. The clearfix hack to clear floats, the 100% padding hack to make square divs, not to mention semi-randomly applying unrelated properties to trick Internet Explorer into doing your bidding.

At the time, the browser was a devious foe to be defeated through sheer cunning and arcane incantations. Today, the perfect property is waiting and just a copy-paste away on MDN.

The new era of CSS

But today things are vastly different: not only are things moving much faster, but browser vendors actually care about making developers happy! I know, I couldn’t believe it either. But I run the yearly State of CSS developer survey (which is open now by the way — go take it!) and I know for a fact that browser development teams use the survey results (among many other data points) to inform their roadmap.

Beyond this, Google has also helped finance my work on the survey, and even hired Lea Verou to take the lead on selecting this year’s survey questions.

It’s not just Google. It’s become fashionable to bash Safari and Apple in general (sometimes deservedly so), but you can’t deny how passionate someone like Jen Simmons is about listening to developers and improving the web.

And not only are browser vendors improving CSS on their own; they’re even collaborating across battle lines with initiatives such as Interop 2023 to help reduce inconsistencies and incompatibilities between browsers.

Too much of a good thing?

The result of all this is that we are now faced with an embarrassment of CSS riches, and it can be hard to catch up. CSS Grid started being supported in major browsers almost five years ago, yet I still check a reference every time I use it. And as cool as subgrid seems, I’ve yet to even try it out.

During the process of selecting which CSS features to include or not in the State of CSS, Lea and myself considered many features, but we also rejected quite a few. Some examples of the feature we didn’t include are:

  • The linear() easing function, which lets you define easing curves with more granularity. 
  • The env() function, which lets you use variables defined by the browser or device. 
  • The scrollbar-width property, which helps control a scrollbar’s appearance. 
  • The margin-trim property, which lets you control how a container’s children’s margins behave. 

These are all potentially very useful, and would’ve all been big news during the CSS drought of past years. But in today’s context they have to fight for attention with much larger announcements, like the has() selector or CSS nesting!

Not excited

As Silvestar Bistrović writes, he is “not that excited about all these new CSS features.” This found an echo on Twitter, with Sara Soueidan stating that what she cares about is “practicality, not how shiny a feature looks at the moment.”

This may seem like a negative attitude, but I think it’s understandable. Nobody can be expected to keep up with so many new features!

Another unintended (or maybe, intended?) consequence is that the more complex CSS becomes, the more it raises the bar for any new company wanting to develop a browser engine — to say nothing of the added workload when it comes to maintaining and documenting all these new features. 

CSS overreach

There’s also the very valid concern that CSS might be branching out into areas it’s not quite suitable to handle. That’s another thing Sara Soueidan pointed out when reacting to the new CSS Toggles experimental implementation (here’s a ticket discussing it):

Many have made the very reasonable point that this kind of behavior would be best handled by a new HTML element instead of managing toggle state purely through CSS, and that CSS may not be the best medium to ensure accessibility issues are properly addressed. 

When CSS takes over something that was previously handled through JavaScript, this is generally seen as a good thing, as it often reduces the amount of code the browser has to load. So, I’m cautiously optimistic about CSS Toggles and trust that the CSS Working Group will properly address the concerns of the community. But there may yet come a day when we start to worry that CSS may be expanding beyond its borders and encroaching on HTML and JavaScript’s responsibilities.

New expectations

And maybe this is what needs to change: maybe we should drop the expectation that CSS developers have to know all of CSS? 

This expectation stems from the days where CSS was an afterthought, that little annoying syntax you had to learn to make your button blue and bold just like the client asked. But I think we need to accept that today’s CSS might just be way too vast for a single person to master, especially in addition to other front-end duties.

As Michelle Barker puts it:

And that’s where I, myself, land in the end. I’ve made my peace with the fact that I will probably never use — or even know about — all possible CSS features. And this is coming from someone who runs a survey about CSS!

But these new features will surely be useful to someone. Someone will write blog posts about them, create cool CodePens with them, give talks about them. That person will be a cool, young, energetic developer who still have all their hair. In other words, it won’t be me — and that’s fine. 

And maybe you’re worried that this new developer will be overwhelmed by all the stuff they have to learn at once. But do keep in mind all the things they won’t have to learn about, precisely because it’s been replaced by these newer alternatives. I know I’d take that deal anytime.

But think about it: in the past couple years, not only have we seen a huge increase in the number of devices we need to cater to, we’ve also started to recognize that we all consume the web in slightly different manners, whether due to disabilities, current context, or just personal preferences. Shouldn’t CSS adapt to this new reality?

Now, I have to confess this has all made me feel a bit nostalgic… so excuse me while I go clear a couple floats, just for old time’s sake.

As I mentioned, the yearly State of CSS survey is now open. Whether you think there’s too much CSS or not, the survey is a great way to let browser developers know how you feel, so go fill it out if you have 10 minutes. 

Is There Too Much CSS Now? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.