avatarXiuer Old

Summary

The article discusses five new CSS features that are changing the way developers write CSS, including the :has() selector, :focus-within pseudo-class, cascade layers, new transform properties, and the env() function.

Abstract

The web development landscape is being reshaped by the introduction of several innovative CSS features. The :has() selector allows for styling based on child elements, enabling more dynamic and context-aware styling. The :focus-within pseudo-class simplifies the process of styling elements when a child element is focused. Cascade layers introduce a new way to organize and control CSS specificity, making stylesheets more maintainable. The new transform properties aim to streamline the process of applying transformations to elements without the need to rewrite complex transform functions. Lastly, the env() function opens up possibilities for CSS to access and utilize system-level styles, enhancing the adaptability of web applications to various user agent environments.

Opinions

  • The author views the :has() selector as a significant advancement, particularly for its practical applications in form validation and styling based on child element states.
  • The :focus-within pseudo-class is seen as a convenient tool for improving user interaction and feedback, especially for complex nested elements.
  • Cascade layers are considered a unique and underutilized feature that could revolutionize the way CSS is structured and written, offering a more intuitive approach to managing style precedence.
  • The shift away from traditional transform properties is welcomed as a way to reduce repetitive code and simplify the application of complex transformations.
  • The env() function, while currently limited in scope, is regarded as having substantial potential to change how CSS interacts with user agent styles, potentially leading to more responsive and adaptive designs.
  • The author expresses a desire for future expansions of the env() function, suggesting possible uses like accessing the browser's zoom level or default operating system fonts.

5 New Features That Will Change the Way You Write CSS

Photo by Nick Karvounis on Unsplash

The past year has seen an explosion of new CSS features that have revolutionized the way we write CSS. No matter where you are in your web development journey, there will be new things to learn. For a simple styling language, it does change pretty fast!

1. :has() selector

The new selector works in every browser except Firefox, but it’s supported when the flag is turned on, so we know it’s coming.

:has() selectors allow us to style parent elements based on their child elements. For example, we can do this:

figure { background: white; }

figure:has(img) { background: grey; }

Changes its background to gray if figure within the element . img of course, there are more practical uses for this, such as:

form:has(input:invalid) { /*there an invalid input*/
     background: red; 
}

form:not(:has(input:invalid)) { /*all inputs valid*/
     background: green 
}

That’s :not(:has(input:invalid)) cool, but kind of confusing. Basically, if the form has no invalid ones input, it only contains valid ones inputs, so it's a valid form 👍.

2. :focus-within pseudo-class

You’ve probably been using :focus for a while, but :focus only works on the current element. What if you want to know if the user is focused on a child element? iframe this is useful if you have a sublink on the page or in a menu. You can use it like this:

div:focus-within { background: red; }

Turns red if the user follows div anything in the . div it's very convenient! You can even do the same in our previous example!

form:has(input:invalid):focus-within {
     background: red; 
}

form:not(:has(input:invalid)):focus-within {
     background: green 
}

That way, the form won’t turn red or green unless the user interacts with it. An empty form is technically an invalid form 😱

3. Cascade layer

This one is a bit unique, and while I’ve never seen it used in practice, there is definitely one. Start with this HTML:

<div class="box">
  <p>Hello, world!</p>
</div>

Select <p> the tab:

p { font-size: 18px }

But what if we want to add more styles? Well, CSS cascades down, so we just need to add some styles after it.

p {
  font-size: 18px
}

p {
  font-weight: bold;
  font-size: 20px;
  color: red;
}

So far, it’s just basic CSS, nothing revolutionary. But what if we wanted to add styles to font-weight and color, but keep font-size the ? The obvious solution is to remove font-size: 20px this line, but now there is a new way, using "Layers":

p {
  font-size: 18px;
}

@layer type {
  p {
    font-weight: bold;
    font-size: 20px;
    color: red;
  }
}

The result of this CSS will display paragraphs in bold, red, and with a font size of 18 pixels . Read it again. Although the second p selector is more specific (since it's at a deeper position), since it's “type” inside the layer, the 20px fontsize won't override the 18px fontsize

Think of it that way, @layer everything inside is written at the top of the stylesheet, like this:

/*How it's written*/
p {
  font-size: 18px;
}
@layer type {
  p {
    font-weight: bold;
    font-size: 20px;
    color: red;
  }
}

/*How it's rendered*/
p {
  font-weight: bold;
  font-size: 20px;
  color: red;
}
p {
  font-size: 18px;
}

We can also organize the rendering order of layers in this way:

@layer template, unique;

p { font-size: 18px; }
@layer unique {
  p {
    font-size: 12px;
  }
}
@layer template {
  p {
    font-size: 20px;
  }
}

This renders because at the top of the style sheet, template before unique the .

p {
  font-size: 12px;
}

p {
  font-size: 20px;
}
p {
  font-size: 18px; 
}

It is also possible to import specific layers in the stylesheet, just like importing JS modules or Python libraries:

@import "style.css" layer(template);

4. Goodbye Transforms

I remember when transforms first came out, they were awesome. You can scale elements, rotate them, distort them, and even turn them into 3D shapes.

But they always have a problem. If you have CSS like this:

div {
   transform: translate(-50%, -50%) rotate(10deg)
}

Then you want to add a hover effect to zoom, you’ll have to write it again:

div:where(:hover, :focus) { 
   transform: translate(-50%, -50%) rotate(10deg) scale(1.1)
}

This coding is such a headache 😔

Thankfully, now we have a new option. We can ditch them entirely transforms, and style our elements without them.

div {
   translate: -50%, -50%;
   rotate: 10deg;
}
div:where(:hover, :focus) {
   scale: 1.1;
}

5. code from user agent

CSS custom properties allow us to save styles in code and reuse them later, like this:

:root {
  --color: red;
}

p { var(--color); }

img { border: 2px solid var(--red); }

However, while these are defined by us programmers, there are other styles defined by user agents. We can env() access them through styles. Currently, only eight such styles are available:

/*the safe-area-inset-* styles */
env(safe-area-inset-top)
env(safe-area-inset-right)
env(safe-area-inset-bottom)
env(safe-area-inset-left)

/*the titlebar-are-* styles */
env(titlebar-area-x)
env(titlebar-area-y)
env(titlebar-area-width)
env(titlebar-area-height)

The first four define the padding for the top, right, bottom and left of the browser window. This is handy on non-square screens, like smartwatches or some phones whose screens curve to the edges. You can use these directly safe-area-inset-*, but their value is 0 pixels.

These titlebar-area-* styles are only available for Progressive Web Apps, and only when using window-controls-overlay display_override the value. They can be used to prevent the PWA from covering the minimize, maximize and close buttons.

Well, I can’t think of any other instances where a user agent could communicate with a stylesheet to determine how it should be displayed. Yes, you can @media (prefers-color-scheme: dark) check for dark mode using the , or you can force the printer to print something with a background image.

@media print {
  * {
      -webkit-print-color-adjust: exact;
      print-color-adjust: exact;
  }
}

But these are not the same as actually getting the value from the user agent and putting it in the stylesheet. Although the current application is limited, I can imagine future applications may be to obtain the default operating system font or obtain the browser’s zoom level through something like this.

body { font-size: calc(100% * env(browser-zoom-level)); }

We can’t do that at the moment, and it’s a problem for developers.

While env() there aren't many use cases for , it does have the potential to change the way we write CSS, and it's something we should be aware of.

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you go:

CSS
Programming
Web Development
Technology
Coding
Recommended from ReadMedium