|

Modern CSS — Empowering the Web Designers of Tomorrow

Modern CSS

Stay ahead with modern CSS. Join me in my journey in uncovering recent CSS releases that empower tomorrow’s web designers today.

CSS ten years ago: you may have a little bit of flexbox. It’s buggy but that’s the best we can do, sorry.
CSS now: what do you need? clamp? aspect-ratio? container queries? :has? inert? cascade layers? not only is it possible, it’s already shipping!

Mayank Gupta

Feeling like you’re on a rollercoaster ride, hanging on for dear life as the world of CSS continues to evolve at breakneck speed? You’re not alone! This is the world of modern CSS, and let me tell you, it’s packed with endless exciting possibilities.

Modern CSS is our ticket to the future, a shiny toolbox full of superpowers that is revolutionizing how we bring our creative designs to life. It’s like a wand in the hands of Harry Potter, enabling us to conjure up some magical stuff on the web. And the best part? We’re only scratching the surface of what we can achieve.


Modern CSS Living Guide

In the spirit of transforming overwhelm into mastery, and because teaching really is the best way to learn, I’ve embarked on a journey to create this Modern CSS Living Guide. It’s my personal lighthouse in the stormy seas of modern CSS, a go-to reference that keeps me on track as I navigate through my projects.

So, jump on board and let’s ride the modern CSS wave together. I hope this guide serves as your trusty compass, empowering you to create the web designs of tomorrow. Enjoy!


aspect-ratio Property

Think of the aspect-ratio CSS property like your web design’s personal fitness trainer. It helps your boxes stay in tip-top shape by setting their ideal proportions — great for responsive iframes. So, whether you’re doing auto sizes or other cool layout stuff, this handy-dandy tool has got your back!

Code Example

.container {
    aspect-ratio: 16 / 9;
    width: 100%;
}

Stable: September 2021

Aspect Ratio Resources


:has Pseudo Class

The :has CSS class is a relational pseudo-class that allows you to select an element if it contains a certain other element. In essence, it elevates your CSS coding to a new level by giving you the power to select and style parent elements based on their children—a feat traditionally outside the realm of CSS.

Code Example

.card:has(img) {}

/* 5 or more items show next to each other */
ul:has(:nth-child(n + 5)) li {
    display: inline;
}

/* Add ; after each item except last item */
ul:has(:nth-child(n + 5)) li:not(:last-child)::after {
    content: ";";
}

Supported in Firefox behind the layout.css.has-selector.enabled flag

:Has Resources


:is Pseudo Class

The :is function in CSS is a potent tool that simplifies your style sheets by grouping multiple selectors into one. It boosts efficiency by condensing complex, repetitive code, enabling you to style various elements with similar attributes using a single line of CSS. This makes your code cleaner, easier to maintain, and potentially more performant.

Code Example

.container :is(h2, p, button) {
    color: lightskyblue;
}

/* Same as */
.container h2,
.container p,
.container button {
    color: lightskyblue;
}

Stable: June 2023

:Is Resources


inset Property

The modern CSS inset property is a great little shortcut for the traditional top, right, bottom, left properties. It’s great when used in conjunction with the position property for creating layouts & handling overlay items, like modals or dropdowns.

Code Example

div {
    position: relative;
    width: 300px;
    height: 300px;
    background-color: lightblue;
}

.container {
    position: absolute;
    inset: 20px 30px 50px 70px;
    background-color: coral;
}

Stable: June 2023

Above, we have a relatively positioned div element with a width and height of 300px. Inside it, we have an absolutely positioned box that is offset from the edges of the parent div. The inset values are provided in a clockwise order starting from the top, just like the margin and padding properties. This means the #box will be 20px from the top, 30px from the right, 50px from the bottom, and 70px from the left edge of the parent div.

Inset Property Resources


line-clamp Property

Picture this: you have a block of text, and you want to limit the number of lines it occupies, while still keeping it stylish and readable. That’s where line-clamp comes to the rescue! It’s like a cool stylistic scissor that trims down your text, making it fit neatly within a specific number of lines.

Code Example

.container {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
}

Stable: May 2023

In this snippet, this CSS code is limiting the number of lines the text should wrap. It helps create a neat and visually appealing presentation of text within the designated container.

line-clamp Property Resources


-inline & -block Properties

The margin-block and margin-inline properties, alongside their padding counterparts, are incredibly useful when you’re dealing with internationalization or creating layouts that need to adapt to different writing modes (like left-to-right or right-to-left). They add a dash of logical thinking to your stylesheets, allowing you to define margins and padding in terms of block flow and inline directions, rather than just top, bottom, left, and right. It’s also a great way to code down on code when defining left/right (inline) or top/bottom (block) spacings.

Code Example

.post {
    padding-block: 20px; /* Applies to top and bottom, regardless of writing mode */
    padding-inline: 10px; /* Applies to left and right in LTR mode, right and left in RTL mode */
}

.post-title {
    margin-block-start: 0; /* No top margin */
    margin-block-end: 10px; /* Bottom margin, regardless of writing mode */
}

.post-content {
    margin-block-start: 0; /* No top margin */
    margin-block-end: 20px; /* Bottom margin, regardless of writing mode */
}

Stable: June 2023

In this example, .post gets 20px padding on the top and bottom, and 10px padding on the left and right in left-to-right languages, with the directions flipped in right-to-left languages. This is achieved using padding-block and padding-inline.

Within each .post, we’ve styled .post-title and .post-content with margin-block-start and margin-block-end, which control the vertical margins. This means that regardless of the writing direction, .post-title and .post-content will have consistent vertical spacing.

-inline & -Block Property Resources


clamp Function

In the fast-moving world of modern CSS, the clamp() function is a game-changer. It allows you to smoothly control the sizes of your elements so they look great on every device using three arguments: minimum size, preferred size, and a maximum size.

Code Example

body {
    font-size: clamp(18px, 5vw, 32px);
}

Stable: September 2021

In this example, the font size of the text in the body of the webpage will never get smaller than 18px or larger than 32px. In between these values, it will scale with the width of the viewport, providing a more responsive design.

Clamp function Resources


Viewport Units

  • vw: Viewport Width — Represents a % of the width of the viewport.
  • vh: Viewport Height — Exact same as vw but for height instead.
  • vmin & vmax: Represents the max & min viewport dimension.
  • vi: Viewport Inline — Represents the inline direction of your document.
  • vb: Viewport Block — Represents the block direction of your document.

Viewport Unit Modifiers

  • s: Small — Represents the smallest possible viewport.
  • l: Large — Represents the largest possible viewport.
  • d: Dynamic — Represents the current viewport size.

Code Examples

/* vw & vh: Viewpoint height */
.full-screen {
    height: 100vh;
    width: 100vw;
}

/* vmin & vmax: Min & max of the viewport dimension */
.no-overflow {
    height: 100vmin;
    width: 100vmin;
}

/* vi: Viewport inline */
.horizontal {
  writing-mode: horizontal-tb;
  width: 10vi; /* Same as 10vw */
}

.vertical {
  writing-mode: vertical-lr;
  height: 10vi; /* Same as 10vh */
}

/* vb: Viewport block */
.horizontal {
  writing-mode: horizontal-tb;
  width: 10vb; /* Same as 10vh */
}

.vertical {
  writing-mode: vertical-lr;
  height: 10vb; /* Same as 10vw */
}

Stable: November 2022

Viewport Unit Resources


Individual Transform Properties

Code Example

.target {
    rotate: 30deg;
    scale: 1.2;
    translate: 50% 0;
}

Stable: August 2022

Modern CSS Transform Property Resources


CSS Nesting

Code Example

.card {
    /* card styles */

    .title {
        /* element styles */
    }

    &:hover,
    &:focus {
        /* modifier styles */
    }

    @container (width >= 300px) {
        /* container query styles */
    }
}

Stable: Almost, not quite yet. Available in FF Nightly.

CSS Nesting Resources


Cascade Layers

Code Example

/* Base styles */
@import 'styles/base/normalize.css' layer(base);
@import 'styles/base/base.css' layer(base);
@import 'styles/base/theme.css' layer(theme);
@import 'styles/base/typography.css' layer(theme);
@import 'styles/base/utilities.css' layer(utilities);

/* Layout styles */
@import 'styles/layout/grid.css' layer(layouts);

/* Component styles */
@import 'styles/components/cards.css' layer(components);
@import 'styles/components/footer.css' layer(components);

Stable: March 2022

CSS Cascade Layer Resources


Scope

Code Example

@scope (.container) to (.content) {
    img {
        max-width: 2rem;
    }
}

Color Spaces

  • oklch
  • hsl & hsla
  • rgb & rgba
  • Hex
  • Color Names
  • p3

Modern CSS Color Unit Resources

  • WWDC23: Overview of the new p3 color space

color-mix

Code Example

.element {
    background: color-mix(in oklch, var(--color-1), var(--color-2));
    color: color-mix(in var(--color-space), var(--color-1), var(--color-2));
    border-color: color-mix(in srgb, var(--color-1), transparent var(--alpha-percent));
}

Color-gamut Media Query

Code Example

.main {
    background-image: url("photo-srgb.jpg");
}

@media (color-gamut: p3) {
    .main {
        background-image: url("photo-p3.jpg");
    }
}

Color-gamut Media Query Resources

  • WWDC23: How to use the color-gamut media query

Relative Color Syntax

Code Example

:root {
    --primary: lightpink;
    --complement: hsl(from var(--primary) calc(h + 180deg) s 1);
    --primary-a10: hsl(from var(--primary) h s l / 10%);
    --primary-a20: hsl(from var(--primary) h s l / 20%);
    --primary-a30: hsl(from var(--primary) h s l / 30%);
    --primary-a40: hsl(from var(--primary) h s l / 40%);
    --primary-a50: hsl(from var(--primary) h s l / 50%);
}

Container Queries

Code Example

@container (width > 15em) {}

Container Query Resources


Style Queries

Code Example

@container style(--rain: true) {}
@container style(--sunny: true) and (--cloudy: true) {}

Range Queries

Code Example

@container style(--rain > 75%) {}
@container style(20% < --clouds <= 50%) {}

State Queries

Code Example

@container stats style(--theme: dark) {
    .stat {}
}

State Queries Resources


text-wrap: balance (& pretty)

Code Example

.heading {
  text-wrap: balance;
  text-wrap: pretty;
}

@supports selector()

Code Example

@supports selector(:has(a)) {
    .post {
        display: none;
    }

    .filter-bar:has(#css-tag:checked) ~ .post:has([data-tag="CSS"]),
    .filter-bar:has(#html-tag:checked) ~ .post:has([data-tag="HTML"]) {
        display: block;
    }

    .filter-bar {}
}

@supports not selector (:has(a)) {
    .filter-bar {
        display: none;
    }
}

Trigonometric Functions

Code Example

.menu-item {
    --radius: calc(var(--btn-size) + var(--extra-space));
    transform: translateX(calc(cos(var(--angle)) * var(--radius)) translateY(calc(sin(var(--angle * 1) * var(--radius)));
}

Popover

Code Example

<ul role="menu" id="radial-menu" popover></ul>
<button popovertarget="radial-menu">Open Popover</button>

Anchor Positioning

Code Example

<ul role="menu" id="radial-menu" popover anchor="menu-trigger"></ul>
<button popovertarget="radial-menu" id="menu-trigger">Open Popover</button>

@position-fallback

Code Example

:root { --spacer: 0.5rem; }

@position-fallback --top-then-bottom {
    @try {
        bottom: calc(anchor(top) + var(--spacer));
        left: anchor(center);
    }

    @try {
        top: calc(anchor(bottom) + var(--spacer));
        left: anchor(center);
    }
}

#my-tooltip {
    position-fallback: --top-then-bottom;
    translate: -50% 0;
}

@starting-style

Code Example

.setting-popover {
    &:popover-open {
        /* 0. Before open */
        @starting-style {
            transform: translateY(20px);
            opacity: 0;
        }
        
        /* 1. Open state */
        transform: translateY(0);
        opacity: 1;
    }

    /* 2. Exit state */
    transform: translateY(-50);
    opacity: 0;
    transition: transform 0.5s, opacity 0.5s, display 0.5s;
}

<selectmenu>

Code Example

<selectmenu>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</selectmenu>

Scroll-driven Animations

Coming soon!


Native Masonry Layouts

Code Example

.container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    grid-template-rows: masonry;
}

Modern CSS Masonry Resources

  • MDN Web Docs: The CSS masonry grid layout specification
  • WWDC23: Quick overview of Safari’s release on the masonry layout

margin-trim

Code Example

.card {
    padding: 1rem;
    margin-trim: block;
}

.nav {
    display: flex;
    margin-trim: inline;
    padding: 0.25rem 1rem;
}

CSS margin-trim Resources


Learn More Modern CSS


Wrapping Up

Wheww.,, that was a lot. Our magical ride through the ever-evolving landscape of modern CSS comes to a close. What a journey it’s been! We’ve explored the ins and outs of the latest CSS selectors, experimented with queries, and even had a bit of fun along the way.

Remember, this vibrant world of modern CSS is always spinning, always changing, and it’s our job as frontenders to keep up with its rhythm. This quick reference guide is your key to unlocking the full potential of modern CSS, helping you push the boundaries of what’s possible in web design.

So, whether you’re just dipping your toes into the waters of modern CSS or you’re an old hand ready to ride the biggest wave, don’t forget to bookmark this guide. It’s your trusty compass, your lighthouse, your map to the stars in the vast universe of modern CSS.

Until next time, stay curious, keep experimenting, and above all, let’s continue to empower the web designers of tomorrow with modern CSS. Happy coding!

Share Your Thoughts

Your email address will not be published. Required fields are marked *

Latest Articles