O'Reilly

7 Things You Didn’t Know You Could Do with CSS

By on  
CSS Filters

CSS and JavaScript, believe it or not, are starting to overlap as CSS adds more functionality. When I wrote 5 Ways that CSS and JavaScript Interact That You May Not Know About, people were surprised at how CSS and JavaScript have come to overlap.  Today I will highlight seven tasks you can accomplish with CSS -- no JavaScript or imagery required!

CSS @supports

Every good front-end developer feature-tests before using features which a browser may not have.  Feature testing has always done with JavaScript, and many people use Modernizr, an impressive utility packed with loads of well-tested routines, to do that feature testing.  A new API, however, has come along to let you do feature tests with CSS:  @supports.  Here are a few samples of how @supports works:

/* basic usage */
@supports(prop:value) {
	/* more styles */
}

/* real usage */
@supports (display: flex) {
	div { display: flex; }
}

/* testing prefixes too */
@supports (display: -webkit-flex) or
          (display: -moz-flex) or
          (display: flex) {

    section {
      display: -webkit-flex;
      display: -moz-flex;
    	display: flex;
    	float: none;
    }
}

This new @supports feature, which also has a JavaScript counterpart, is well overdue and we can look forward to using it soon!

CSS Filters

Write a service to modify an image's color shades and you can sell it to Facebook for a billion dollars!  Of course that's an over-simplification but writing image filters isn't exactly a science.  I wrote a tiny app my first week at Mozilla (which won a contest, BTW...just sayin') which used some JS-based math to create image filters with canvas, but today we can create image filters with just CSS!

/* simple filter */
.myElement {
	-webkit-filter: blur(2px);
}

/* advanced filter */
.myElement {
	-webkit-filter: blur(2px) grayscale (.5) opacity(0.8) hue-rotate(120deg);
}

This type of filtering only masks an image's original view and doesn't save or export the image with said filter, but it's great for photo galleries or anywhere else you'd like to add flare to an image!

Pointer Events and Bricking Clicks

The CSS pointer-events property provides a method to effectively disable an element, so much so that clicks on a link don't trigger a click event through JavaScript:

/* do nothing when clicked or activated */
.disabled { pointer-events: none; }
/* this will _not_ fire because of the pointer-events: none application */
document.getElementById("disabled-element").addEventListener("click", function(e) {
	alert("Clicked!");
});

In the example above, the click event wont even fire due to the CSS pointer-events value.  I find this of massive utility as you don't need to do className or attribute checks everywhere to see if something is disabled.

Slide Down & Slide Up

CSS affords us the ability to create transitions and animations but oftentimes we need JavaScript libraries to give us a hand in modifying a few things and controlling the animation.  One such popular animation is the slide up and slide down effect, which most people don't know can be accomplished with only CSS!

/* slider in open state */
.slider {
	overflow-y: hidden;
	max-height: 500px; /* approximate max height */

	transition-property: all;
	transition-duration: .5s;
	transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
}

/* close it with the "closed" class */
.slider.closed {
	max-height: 0;
}

A clever use of max-height allows the element to grow and shrink as needed.

CSS Counters

We'll always have a giggle at what the term "counter" means on the internet, but CSS counters are another thing entirely.  CSS counters allow developers to increment a counter and display it via :before or :after for a given element:

/* initialize the counter */
ol.slides {
	counter-reset: slideNum;
}

/* increment the counter */
ol.slides > li {
	counter-increment: slideNum;
}

/* display the counter value */
ol.slides li:after {
	content: "[" counter(slideNum) "]";
}

You often see CSS counters used in slideshows at conferences and even in lists like a table of contents.

Unicode CSS Classes

There are loads of CSS best practice documents out there, and they'll all start with how to name your CSS classes.  What you'll never see is one of those documents telling you to use unicode symbols to name your classes:

.ಠ_ಠ {
	border: 1px solid #f00;
	background: pink;
}

.❤ {
	background: lightgreen;
	border: 1px solid green;
}

Please don't use these.  Please.  BUT YOU CAN!

CSS Circles

CSS triangles are a neat trick but so are CSS circles.  By abusing CSS border-radius, you can create flawless circles!

.circle {
	border-radius: 50%;
	width: 200px;
	height: 200px; 
	/* width and height can be anything, as long as they're equal */
}
CSS Circle

You can add gradients to your circles and you can even use CSS animations to spin them around!  CSS has a more uniform API for Shapes coming but you can create circles with this hack now!

There you have it:  seven things you can do with CSS that you may be surprised at.  A few are quite useful, a few are more edge cases.  Let me know if I've missed an awesome CSS task that you use frequently!

Track.js Error Reporting

Recent Features

Incredible Demos

Discussion

  1. Jeremiah Megel

    Yes, but how do we know whether it supports @supports?

    • @supports-ception!

    • Sam Daitzman
      @supports @supports {
          @supports transition {
              transition: ...;
          }
      }
      

      Easy :)

  2. I guess I feel its a bit of an exaggeration in stating you can achieve the slide up + down effect with only CSS when you’re demo uses JS to toggle the class name. I guess I feel like it’d be slightly more accurate if you used a label + input combo and checked input:checked + selector or something to setup your transition. Might give people the sense they could actually do that without JS otherwise.

    Had no idea pointer-events: none would prevent js listeners though, thats really interesting.

    • If you wanted to avoid JS altogether you could possibly do something fancy with :target

  3. { pointer-events: none; } not only prevents the event, it even passes the event to the element below.
    This way i was able to style a select field arrow, by overlaying a div with { pointer-events: none; }, so when clicked, the select list opens.
    This is really, really nice.

  4. Fantastic article, thanks! Also loved the picture of Alterra coffee, Milwaukee present (although now they are Colectivo I still call them Alterra)

  5. Also we can achieve kind of container layering with some pseudo class like before, check below link for details.

    http://sankk.in/not-subscribed/

  6. There is one problem with max-height trick, is that elements with different heights transitions with same animation speed. Here is a simple example http://codepen.io/suez/pen/zhcad

    Basically, if you have max-height:500px on hover, and elements like 100/200/400 px height, it will cause them all to transition with speed of 500px/transition-time. And 100px element will animate 5 times faster than you need.

    • Yeah, that majorly sucks. When you don’t know the height of whatever element you’re animating, you have to set the open max-height to something you know it’ll probably never exceed (1000px) which means the timing is funny on the animation.

      * Sigh *

  7. Brandon

    That pointer-events thing just blew my mind.

  8. Benjamin Knight

    Transitioning on width & height (and other box-model properties) has pretty lousy runtime performance as they invalidate the layout causing reflows. I recommend using position and overflow to get a smoother effect.

  9. This is just amazing, specially the slider one. Thanks a lot…

  10. CSS-geek stuff! ThanX!

  11. Paul Ferguson

    A few new points I didn’t know, but can we refrain from these titles “n Things You Didn’t Know – “, sound like you presume your readers are idiots and will have never heard of and or your points.
    I usually avoid them but you do post so good titbits.

  12. also for perfect circles,

    .circles {
        width: 200px;
        height: 200px;
        border-radius: 9999em;
    }
    

    will do the job ;)

    • 9999em? Interesting! Thanks for the heads up!

    • Luca Rosaldi

      The difference between 50% and 9999em (or any other non-percentage unit) is that the former actually produces ovals instead of circles when width and height are not the same.

      Demo: http://codepen.io/LucaRosaldi/pen/rgifI

  13. Amazing article. Mind blowing points, I knew some points but others have opened my mind. Simply fantastic.

  14. Want to use pointer events none. Seems more clean (1 line of CSS) than listening for click event and return false. Would be nice to have browser support charts for each of these so we don’t have to cross check caniuse etc

  15. Nice post David!

    Just wanted to mention that pointer-events only works with SVG’s in IE, which is annoying but can be worked around.

    Also, changing the border-radius: 50% to 50em (or just any high, non percentage unit) makes it work also in older Androids (<=2.3).

  16. These are just perfect thank you. Slide up and down are great

  17. Fantastic loved it thanks :)

    The css pointer-events property was amazing didn’t know abt it, i was using Jquery where i would select the element and then unbind the click event. for links i needed to use the event.preventDefault() stuff.

  18. Animating the height of a div in that way would be extremely useful with responsive sites whereby you could alter the max height property within your media queries. Trying to achieve that with js alot trickier. Would have saved me alot of time on my last job

  19. Khagesh Sharma

    pointer-events does not block any event done via keyboard. So, if some link is focused or navigated using tab and enter is pressed it will fire click event.

  20. Interesting thing with pointer-events : you can nest elements so that the wrapper has none and the child auto. The child won’t inherit its parent value, and so it will receive click events. Same behavior as the visibility property, btw.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Follow Redirects with cURL

    I love playing around with cURL. There's something about loading websites via command line that makes me feel like some type of smug hacker, just like tweeting from command line does. I recently cURL'd the Google homepage and saw the following: I found it weird that Google...

  • Developers Have WordPress, Amateurs Have Squarespace, Professional Designers Have the NEW Webydo!

    Web design platforms have traditionally come in one of two varieties. There are the solutions like WordPress and Drupal that are incredibly powerful, but an understanding of web development and coding is required to be able to use those platforms effectively. On the other side of the...

  • Chris Coyierâs Favorite CodePen Demos II

    Hey everyone! Before we get started, I just want to say it’s damn hard to pick this few favorites on CodePen. Not because, as a co-founder of CodePen, I feel like a dad picking which kid he likes best (RUDE). But because there is just so...

  • GSAP + SVG For Power Users: Motion Along A Path

    Now that the GreenSock API is picking up steam, there are many tutorials and Getting Started guides out there to provide good introductions to the library, not to mention GreenSock’s own Forum and Documentation. This article isn’t intended for beginners, but rather a...

  • Copy a Directory from Command Line

    Copying a directory for the sake of backup is something I do often, especially when I'm trying to figure out why something isn't working when I use an external library.  I'll copy the directory structure as a backup, mess around with the original source until I find a solution,...