Written by Juan Martin García✏️
I’m not the first one to state that the lines between CSS and JavaScript are becoming blurry as both languages evolve.
From custom properties (a.k.a variables) to filters, animations, or math operations, CSS has taken a lot of what we used to do in JavaScript (or in popular CSS preprocessors) and made it available to us, natively.
Both languages serve different purposes. With each browser release, feature release, and increase in properties, CSS is becoming an incredibly powerful language, capable of handling functionality that we previously relied on JavaScript for.
In this post, we’ll learn about some CSS golden nuggets you might not have heard about, that will natively (and gracefully!) handle things like smooth scrolling, dark mode, form validation, and more features that previously required multiple lines of JS trickery to work.
Smooth scrolling
There was a time when we had to rely on JavaScript (or even jQuery) implementations to do this, with window.scrollY
to replicate this behavior. Those days are gone now, thanks to the scroll-behavior property. We can now handle smooth scrolling on our website with, wait for it, one line of CSS code!
html {
scroll-behavior: smooth;
}
Browser support is around 75%, and coming to Edge 76 soon. Check out how it works in the Codepen below:
Dark mode
Dark mode has been the hot trend lately after macOS released its dark mode functionality and Safari implemented the prefers-color-scheme
media feature, which allows us to detect if the user has dark mode enabled by default.
You might think of dark mode as a complex feature to implement, involving CSS variables, different colors for each scheme, and some JavaScript to hook up the necessary click event to target the changes on the website. And while that’s partially true, and it’s currently the standard way to implement it (that’s how I do it on my website) it doesn’t need to be this complicated.
Wei Gao showed us on her blog a clever way to achieve a similar result (more of a reversed mode
) using mix-blend-mode: difference
, one of the blending modes supported on CSS. If you’ve ever played around with Photoshop Blending Modes, this is the same thing but directly on the browser.
Some of its advantages include not having to specify the inverted colors (the blend mode will do that for you), and you can isolate the elements you don’t want to change. Some of its limitations are that you don’t have a full range of colors, and performance can be a concern.
Currently, native browser support is at 77% plus 13% with prefixes (91% global), with Edge support coming on version 76.
For a more in-depth explanation of how this blending mode works, make sure you check Wei’s awesome article on it. For a fun experiment with it, check this Codepen:
Truncate text
This is one of my personal favorites because it’s a common problem I run into when developing websites that rely on a CMS to populate content. Variable length on the copywriting might make your lovely-designed cards look inconsistent across different sizes or resolutions. Dave Rupert has a great article on that matter.
In the past, I’ve always reached out to JavaScript-based solutions without even thinking about it because most CSS techniques for achieving this result were quite “hacky”. But as I work on including a blog to my website, I discovered a couple of CSS properties that, coupled together, might be able to provide a native, easy-to-implement solution. Meet text-overflow
and line-clamp
!
Text-overflow
This is a widely adopted, fully supported native CSS-only solution to control how text behaves when it overflows its containing element. You can set its value to be ellipsis
and that’ll give you the Unicode …
character. So far so good, but its main limitation is that you’ll always get one line of truncated text, regardless of your text’s length. So this might be a perfect fit for titles, but not so useful for excerpts, reviews or long passages of text. See below for an example:
That’s where line-clamp
comes into play.
Line-clamp
The line-clamp
property isn’t new either.Dave DeSandro showed us this technique roughly a decade ago (hence the need for the old flexbox implementation with display: -webkit-box
and -webkit-box-orient: vertical
).
Then what’s new here? Firefox implemented it on version 68 and, wait for it… with the -webkit
prefix! And now that Edge is Chromium-based, we can also use the -webkit
prefix to boost browser support up to 92%.
That means we can now use a combination of three CSS lines to truncate multiple lines of text, like so. The only gotcha here is that the specification for line clamps is part of the CSS Overflow Module Level 3 which is currently in Editor’s Draft, which might imply there could be some changes to the spec. Another thing to consider is that you can’t control the number of characters to show, which might lead to some not so convenient (yet funny) truncation scenarios. But other than that, happy CSS clamping!
Scroll snapping
CSS scroll snapping is another handy functionality Chrome users have had for a while and we can now enjoy on Firefox with its latest 68 release. We will, also, get it on version 76 of Edge, bumping up overall browser support to all major browsers.
Have you ever noticed how some fancy websites will create fullscreen sections, and lock the viewport on specific locations as you scroll? Here’s an example of that behavior.
Getting this to work properly a while back was tricky, with lots of math calculations and JavaScript involved. But now, CSS is capable of creating interactions like this one natively.
It works similarly to Flexbox or CSS Grid in the sense that you need a container element on which you’ll set the scroll-snap-type
and multiple children with scroll-snap-align
set to them, like so:
HTML:
<main class=”parent”>
<section class=”child”></section>
<section class=”child”></section>
<section class=”child”></section>
</main>
CSS:
.parent {
scroll-snap-type: x mandatory;
}
.child {
scroll-snap-align: start;
}
The scroll-snap-type
accepts two different values: mandatory
, which will force the snap to either the top or bottom of the element, or proximity
, which will do the math for you and snap when the content is close enough to the snap point.
Another property we can set on the parent container is scroll-padding
, which might be handy if you have fixed elements on the layout (like a fixed header or, why not, a cookie policy notification 😅) that might otherwise hide some of the content.
For the children, we only have scroll-snap-align
for now, which will tell the container which points to snap to (top, center or bottom).
While it might feel tempting to go willy-nilly with adding scroll snapping on your entire website now that you know this technique can achieve that result with just a couple of CSS lines and no math involved, remember the one and only law of web design, according to Robin Rendle: Don’t mess with the scroll. This technique might be useful for things like sliders, image galleries or some specific sections on your page, but use it sparingly since it can affect performance and the user’s experience overall.
Sticky navigation
Following up on features that previously required a lot of JavaScript math and were pretty expensive to implement performance-wise, we have sticky positioning. Where we previously needed offsetTop
and window.scrollY
we now have position: sticky
to do all the wizardry for us! An element with sticky positioning will behave as a relatively-positioned element until a given point on the viewport is reached to then become a fixed-positioned element. Browser support is up to 92% with the -webkit
prefix.
So, while it might sound as easy as doing something like:
header {
position: sticky;
top: 0;
}
To nicely set your header to be sticky, it’s important to know that the structure of your HTML matters! So for example, if your HTML structure looks like this:
<main>
<header>
<h1>This is my sticky header!</h1>
</header>
<section>This is my content</section>
</main>
The header will only be able to stick on the area that its parent (in this case, the <main>
tag) covers. This “sticky parent” determines the scope on which the “sticky item” can act. This gotcha is better explained by Elad Shechter in this article, and here’s a fun little experiment using this technique.
Bonus to wrap up: @supports media-rule
Even though these CSS features are widely adopted and supported, as discussed above, you might still want to check if they are available on the browser before adding them. If that’s the case, you can use the @supports
feature query, which is widely adopted by browsers and allows you to test if the browser supports a specific property: value
pair before applying a set of styles. The syntax looks as follow:
@supports (initial-letter: 4) {
p::first-letter {
initial-letter: 4;
}
}
With this handy feature query, you can apply a set of styles just on those browsers that support them. The syntax might sound familiar since it’s exactly how we write media queries and is a great way to do what’s called progressive enhancement, using these top-notch features right now on browsers that have them, while preventing inconsistent behavior on browsers that don’t have them. Jen Simmons explains this better on her Resilient CSS videos.
So that’s it! Hopefully, these state-of-the-art CSS features will help you ship a smaller JavaScript bundle, while still creating interesting and compelling UIs. Also, feel free to check out these Codepens again as well.
Editor's note: Seeing something wrong with this post? You can find the correct version here.
Plug: LogRocket, a DVR for web apps
LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
Try it for free.
The post 5 things you can do with CSS instead of JavaScript appeared first on LogRocket Blog.
Top comments (5)
you should never ever force slow scrolling, if user turned it off (or never turned on) on browser level LET THEM BE and don't slow everything down by pushing it into their throat for your own satisfaction
Never imagined Sticky navigation implementation can be so simple. Thanks for sharing great CSS hacks.
the truncate is amazing...!
This is a really nice and well put article. My best are @supports and line-clamp.
I use text-overflow but never heard about line-clamp! Thank you
Some comments may only be visible to logged-in visitors. Sign in to view all comments.