DEV Community

Cover image for 5 things you can do with CSS instead of JavaScript
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

5 things you can do with CSS instead of JavaScript

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.

LogRocket Free Trial Banner

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;
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

CSS:

.parent {
  scroll-snap-type: x mandatory;
}

.child {
  scroll-snap-align: start;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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 Dashboard Free Trial Banner
 
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)

Collapse
 
zakius profile image
zakius

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

Collapse
 
vagoel profile image
Varun

Never imagined Sticky navigation implementation can be so simple. Thanks for sharing great CSS hacks.

Collapse
 
acjunior profile image
André Carlos

the truncate is amazing...!

Collapse
 
cedxix profile image
Cedric D. A

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.