5 things you can do with CSS instead of JavaScript
Tags: css, javascript
Published: 2019-10-29 19:15:04

---
title: 5 things you can do with CSS instead of JavaScript
published: true
date: 2019-10-29 18:00:34 UTC
tags: css,javascript
canonical_url: https://blog.logrocket.com/5-things-you-can-do-with-css-instead-of-javascript/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/l1shha1irgu3gdader4x.png
---
**Written by [Juan Martin García](https://blog.logrocket.com/author/juanmartingarcia/)**✏️

I’m [not the first one](https://davidwalsh.name/css-facts) 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](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## 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](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior) property. We can now handle smooth scrolling on our website with, wait for it, one line of CSS code!

```jsx
html {
  scroll-behavior: smooth;
}
```

Browser support is [around 75%](https://caniuse.com/#feat=css-scroll-behavior), and coming to Edge 76 soon. Check out how it works in the Codepen below:

{% codepen https://codepen.io/imjuangarcia/pen/RwbQLPe %}

## Dark mode

Dark mode has been the hot trend lately after [macOS released its dark mode functionality](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/) 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](https://dev.to/ananyaneogi/create-a-dark-light-mode-switch-with-css-variables-34l8) (that’s [how I do it on my website](http://www.juangarcia.design)) it doesn’t need to be this complicated.

Wei Gao [showed us on her blog](https://dev.wgao19.cc/sun-moon-blending-mode/) 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](https://helpx.adobe.com/photoshop/using/blending-modes.html), 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](https://caniuse.com/#search=mix-blend-mode) (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](https://dev.wgao19.cc/sun-moon-blending-mode/) on it. For a fun experiment with it, check this Codepen:

{% codepen https://codepen.io/imjuangarcia/pen/xxKLMEN %}

## 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](https://daverupert.com/2018/04/pitfalls-of-card-uis/) 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”](https://css-tricks.com/line-clampin/). But as I work on including a blog to [my website](https://www.juangarcia.design), 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](https://caniuse.com/#search=text-overflow) 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](https://twitter.com/desandro) showed us this technique [roughly a decade ago](https://dropshado.ws/post/1015351370/webkit-line-clamp) (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](https://bugzilla.mozilla.org/show_bug.cgi?id=WebKit-line-clamp) 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%](https://caniuse.com/#search=line-clamp).

That means we can now use a combination of three CSS lines to truncate multiple lines of text, [like so](https://codepen.io/imjuangarcia/pen/dybdYbB). The only gotcha here is that the specification for line clamps is part of the [CSS Overflow Module Level 3](https://drafts.csswg.org/css-overflow-3/#propdef--webkit-line-clamp) 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.](https://twitter.com/search?f=tweets&vertical=default&q=karenmcgrane%20truncation%20is%20not&src=typd) 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](https://caniuse.com/#feat=css-snappoints).

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](https://www.artandscience.jp/) 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](https://codepen.io/imjuangarcia/pen/zYORdMK) 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:

```jsx
<main class=”parent”>
  <section class=”child”></section>
  <section class=”child”></section>
  <section class=”child”></section>
</main>
```

CSS:

```jsx
.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 [😅](https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f605.png)) 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](https://www.robinrendle.com/notes/scrolljacking), 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](https://caniuse.com/#feat=css-sticky).

So, while it might sound as easy as doing something like:

```jsx
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:

```jsx
<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](https://medium.com/@elad/css-position-sticky-how-it-really-works-54cd01dc2d46), and [here’s a fun little experiment](https://codepen.io/imjuangarcia/pen/QWLQjqQ) 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](https://caniuse.com/) before adding them. If that’s the case, you can use the `@supports` feature query, which is [widely adopted by browsers](https://caniuse.com/#feat=css-featurequeries) 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:

```jsx
@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](https://youtu.be/T8uxmUQZsck) 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](https://codepen.io/collection/DrGkMr) again as well.

* * * 
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/5-things-you-can-do-with-css-instead-of-javascript/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) 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](https://logrocket.com/signup/).
* * *
The post [5 things you can do with CSS instead of JavaScript](https://blog.logrocket.com/5-things-you-can-do-with-css-instead-of-javascript/) appeared first on [LogRocket Blog](https://blog.logrocket.com).