RSS FeedTwitterMastodonBlueskyShare IconHeart IconGithub IconArrow IconClock IconGUI Challenges IconHome IconNote IconBlog IconCSS IconJS IconHTML IconShows IconOpen Source Software IconSpeaking IconTools IconShuffle IconNext IconPrevious IconCalendar IconCalendar Edit IconNotebook IconObservable Notebooks IconSlash IconGoogle G IconYouTube IconEye Icon
Punk graffiti and sticker style image saying 4 CSS features every front-end developer should know in 2026
A cartoon skull with a hotpink hat on.7 min read

4 CSS Features Every Front-End Developer Should Know In 2026

css
7,627 views · 24 active

2026; I think every front-end developer should know how to query scroll states, trim typographic whitespace, stagger with sibling-index(), and use type safe attr().

This is only some of the CSS that shipped in 2025 you need to know.


This post is a themed post!
Check out 2023, 2024 and 2025.

sibling-index() and sibling-count() #

Earlier this year these were just experiments, now they're available in stable Chrome and Safari!

They let you use an element's position relative to its siblings as values in calculations. For example, you can stagger elements with a transition delay based on their sibling-index().

A nice trick is to subtract 1 so the first element starts immediately:

li {
  transition: opacity .3s ease;
  transition-delay: calc((sibling-index() - 1) * 100ms);
}

Stagger enter stage animations easily by combining with @starting-style!

li {
  transition: opacity .3s ease;
  transition-delay: calc((sibling-index() - 1) * 100ms);

  @starting-style {
    opacity: 0;
  }
}

You can rotate hues in oklch, automatically number elements, and all sorts of fun things.

Resources

@container scroll-state() #

These features fit nicely into progressive enhancement, similar to scroll driven animations, as they're enhancements rather than requirements. IMO at least.

Three states of a scroller are now queryable:
stuck, snapped, scrollable and scrolled.

To start, you need the element that's stuck, snapped, or scrollable to have container-type: scroll-state. Then, a child can query it with @container scroll-state().

An element cannot query itself, but its pseudo elements can!

stuck #

Perfectly know when position: sticky elements are stuck.

/* when .outer-navbar is stuck */
@container scroll-state(stuck) {
  .inner-navbar {
    box-shadow: var(--shadow-3);
  }
}

Use this to help users understand an element will now be overlaying their scroll content.

snapped #

Perfectly know when scroll-snap alignment is active.

/* when <li> parent is snapped */
@container scroll-state(snapped) {
  .box {
    scale: 1.1;
  }
}

/* or not snapped! */
@container not scroll-state(snapped) {
  .box figcaption {
    translate: 0 100%;
  }
}

Great for highlighting the item, or demoting every other item.

scrollable #

Perfectly know when content overflows its container, and in which direction(s).

@container scroll-state(scrollable) {
  .scroll-hint {
    opacity: 1;
  }
}

Use this to toggle hints, scroll indicators, or adjust padding to signal more content.

scrolled #

Perfectly know when content is scrolled in a direction.

@container scroll-state(scrolled: bottom) {
  translate: 0 -100%;
}

Use this for sticky headers or navbars that showy hidey based on scroll direction.

Resources

text-box #

text-box lets you slice half-leading right off a text box!

Web font rendering includes whitespace above and below glyphs for "safe spacing", but sometimes you want pixel-perfect alignment to baselines or x-heights.

Achieve the above image with:

h1 {
  text-box: trim-both cap alphabetic;
}

That one-liner trims spacing above cap height and below alphabetic baselines.

Learn more in my interactive notebook

Perfect for type and grid alignment nerds. I think it'll become the default.

Resources

typed attr() #

There's an advanced version of attr(); type-safe and more powerful.

It allows using HTML attributes directly in CSS with type checking and fallbacks.

Pass colors:

<div data-bg="white" data-fg="deeppink"></div>
.theme {
  background: attr(data-bg color, black);
  color: attr(data-fg color, white);
}

Pass numbers:

<div class="grid" data-columns="3">…</div>
.grid {
  --_columns: attr(data-columns number, 3);

  display: grid;
  grid-template-columns: repeat(var(--_columns), 1fr);
}

This creates a powerful bridge between HTML and CSS.

Here's a scroll snap example where CSS basically controls the enums and HTML must pass valid values to get the desired snap results:

<li scroll-snap="start"></li>
<li scroll-snap="center"></li>
<li scroll-snap="end"></li>
<li scroll-snap="nothing"></li>
[scroll-snap] {
  scroll-snap-align: attr(scroll-snap type(start | center | end));
}

The type() function validates attribute values against allowed keywords. Invalid values fall back gracefully.

Try it on Codepen

Resources

CSS rules.

Now let's laugh at this hilarious obvious AI generated nano banana image I made about us having our cake and eating it too.

Still can't do hands lol

10 comments #

45likes
14reposts
  • Daniel
  • Johannes Odland
  • Fronteers
  • Brecht De Ruyte
  • Daniel ????
  • Chris
  • GENKI
  • Steven G. Harris
  • ralf g.
  • Álvaro Montoro
  • James Nash
  • Bramus
  • Robby Barnes :trekbar:
  • Felix

Join the conversation on

Yo Adam, is there a way to apply text-box trim globally rather than on every element? Peace!
James GullandJames Gulland
You probably don't want to, I tried. There are some gotchas in my experience using it. They may well be my fault but still, ye be warned.
WoodyWoody
Grid-lanes and @scope are game changers.
Rodrigo DiasRodrigo Dias

@argyleink reading this as a Gecko user is like window shopping for trendy clothes... By the time we can use these they'll be old news ????

ChrisChris
I really hope that FF quits AI bandwagoning and starts getting their sh*t together to keep up. I **really** could use style queries, but want to support it.
Mike HerchelMike Herchel
agree, there are enough times you won't want it, especially if you trim to ex-height, that it's not worth a global reset
Adam ArgyleAdam Argyle