7 Things You Didn’t Know You Could Do with CSS
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 */ }
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!
Yes, but how do we know whether it supports
@supports
?@supports
-ception!Easy :)
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
{ 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.
Fantastic article, thanks! Also loved the picture of Alterra coffee, Milwaukee present (although now they are Colectivo I still call them Alterra)
Also we can achieve kind of container layering with some pseudo class like before, check below link for details.
http://sankk.in/not-subscribed/
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/zhcadBasically, 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 of500px
/transition-time. And100px
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 *
That pointer-events thing just blew my mind.
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.
This is just amazing, specially the slider one. Thanks a lot…
CSS-geek stuff! ThanX!
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.
also for perfect circles,
will do the job ;)
9999em
? Interesting! Thanks for the heads up!The difference between
50%
and9999em
(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
Amazing article. Mind blowing points, I knew some points but others have opened my mind. Simply fantastic.
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
http://caniuse.com/#feat=pointer-events — You’re welcome.
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%
to50em
(or just any high, non percentage unit) makes it work also in older Androids (<=2.3).These are just perfect thank you. Slide up and down are great
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 theevent.preventDefault()
stuff.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
pointer-events
does not block any event done via keyboard. So, if some link is focused or navigated usingtab
andenter
is pressed it will fire click event.Interesting thing with
pointer-events
: you can nest elements so that the wrapper hasnone
and the childauto
. The child won’t inherit its parent value, and so it will receive click events. Same behavior as thevisibility
property, btw.You can do more with css, Slide Down & Slide Up can be done with just css and other related stuff wich needed two state you can use checkbox
demo : http://codepen.io/anon/pen/pEzPrg
great article David
Theres other also things to explore like CSS only analytics!
https://github.com/jbtronics/CrookedStyleSheets