CSS has come a long way in recent years, bringing style and interaction to the web. For example just look at all the cool things you can do now with CSS animations!
However there are some common components that people are still reaching to JS to solve when they can achieve the same thing with CSS. Things like: Modals, tooltips, mobile menus, accordions and carousels.
What if I told you that each of these can now be done with CSS alone? That way the functionality renders at the same time as the design and makes it usable by more people.
Rhiana Heath – Things you can do with CSS that used to need JS
— Simeon Johnson (@lostumbrellas) October 31, 2019
All of your users are non-JS users while they’re downloading your JS. – Jake Archibald
CSS makes great no-JS fallbacks… don’t forget the humble NOSCRIPT element. Disabling JS is very easy, there are extensions for most browsers to make it very easy to test. Just remember when you’ve turned them on, or you can get a bit of a surprise when you go and open the next website!
- Have everything show by default, then hide/toggle with JS not CSS.
- Increase JS performance by removing JS you don’t need.
- Progressive enhancement – use CSS for as much functionality as possible. If CSS doesn’t load people usually refresh to get it working.
:focus-within is great for things like dropdown navigation. Focus within tracks keyboard focus, so you can do dropdown navigation with little or no JS (the JS is required for accessibility, to reveal the state of your dropdown using ARIA). The selector scheme can be a little complex so you’ll probably copy and paste this one.
:target can create CSS-only modals, noting you will need to include
aria-modal="true" for a11y. Pros are huge desktop support and no JS; main cons are that it modifies browser URL history, and isn’t supported so well on mobiles. Future – somewhere in the future this may be replaced by the DIALOG element, although that doesn’t seem to be gaining a lot of traction.
:checked has a lot of popular hacks associated with it, using the checked state of checkboxes to show and hide other content. You can build up things like expanders and accordions. Pros are wide browser support; cons are that it doesn’t support nested inputs, and mobile support. Future – DETAILS/SUMMARY. Currently support isn’t complete and it’s hard to style.
column-gap are great for masonry layout, where the order of content doesn’t really matter. Supported in all major browsers so long as you have all your prefixes in order; main con is the lack of control over content placement.
transition can replace a lot of expensive JS libraries used for animations. CSS is great for subtle UI animation. Avoid using transition on all as it tends to create really weird effects and performance problems. Browser support is generally great apart from background images in Safari which just don’t work. Cons are the possible performance issues and it only supports specific properties.
— Simeon Johnson (@lostumbrellas) October 31, 2019
So what can’t CSS do?
- Just like Batman, it has no parents. There is no :parent selector. This makes us all sad.
- Radio button hacks don’t work if you wrap the label around them.
- Accessibility can be impacted, eg. radio buttons aren’t meant to be used for carousels.
- Accessibility can also be an issue because CSS can’t transition dynamic properties like aria-hidden, be careful what you do and test in assistive tech
It’s good to take a step back and ask whether you really need a whole library, and look at what CSS can do.
(laid-back music) – Thanks for that.
Really great to be here.
So I really like CSS, if you can’t tell from my title there.
I think it’s really powerful and I think more and more features are being added and more and more features are being adopted by lots of browsers, and there’s a lot of cool stuff that if you haven’t looked at CSS for a few years you might not know about, and even if you use it every day, you’re still learning more and more things about it. I learnt a few things about it just before with Sarah’s talk, so, that I’m, yeah, really excited about and I’m gonna go play with next time I can. So I guess the question is why use CSS for functionality? We’ve already got our HTML.
I think I actually have the wrong slide deck up, so I might just quickly change that.
Sorry, I’ve given this talk a couple of times, so I’ve just gotta go pick my other one.
So why would we then replace that with CSS when CSS is supposed to just be for styling and for making things look a certain way? Well, this comes to this statistic.
This is something that I came across a few years ago when I was looking into accessibility.
And to me, this is a pretty big number.
At the time, I was still supporting things like IE6 when I was looking into this, and less than 2% of people were using that and we were spending hours and hours and hours and hours to accommodate IE6, which is great.
One is speed and bandwidth.
Accessibility, as I mentioned.
So you’ve probably seen this when you’re out in the middle of nowhere and your phone’s down to 3G and you’re trying to access your website and you’re trying to click on things and your content’s moving up and down and the search isn’t working yet and nothing’s opening and closing and working as it should.
So this is an oldie but still a classic.
I still use this one.
This is the noscript tag in HTML.
There are lots of add-ons for different browsers. These are just a few that I found.
It’s just a little button.
It lives at the top of your browser.
You turn it on and off.
Remember to turn it on before you go to any other website that you’re testing, ’cause yeah, I’ve been caught out a few times, like, why isn’t this working? Oh, yeah, gotta turn it back on.
But yeah, just really super easy to check.
So there’s a few things you can do.
So you might have an accordion or a carousel where you’ve got lots of things hidden and you’re kind of showing them as the user interacts with things.
It’ll look pretty silly, but they’ll at least still see all your content that’s there.
CSS is a lot faster to use.
So one is the pseudo-selector focus.
There’s a new one, focus-within, that I’ll touch on, as well.
So focus is keyboard focus.
As we’re talking about before, keyboard accessibility is the focus one.
So this is when you’re tabbing around your site, what happens when you tab to things? How does it look different? How does it interact? One of the main things I do this with is with drop-down navigation.
So when you’re, there are so many websites I go to where they’ve done it really well for hover and for mouseover and everything and for clicks and jQuery and all those sorts of things, but then they’ve forgotten about the keyboard accessibility and the focus and tabbing to it, as well.
So you can do whole drop-down navigations even with nested ones and things poking out the corners and every other cool things with hovers, with focus, and with focus-within.
Focus-within is a really cool one.
It lets you to tab across and then down into your navigation, as well, so it increases your keyboard accessibility there. And these are, well, focus and hover have been around for a while. Focus-within is pretty new, so I just wanted to point that one out, ’cause I find it quite cool.
And this is my, if I can find my cursor.
So this is my CSS-only drop-down navigation. So I’ve got my, so I’ll show you a bit of the code, but I’ve got some hovers, I’ve got some focus, I’ve got some focus-within then.
And then as you’re hovering over things and focusing on things, you can add some cool transitions and some animations and stuff there, which is really cool.
The con is that this is one of the hardest ones that I have here.
I always have to have it written down and come back to it and copy and paste it from everywhere.
It’s quite fiddly.
You kinda have to have a wrapper div for the hover and then you’ve got your button on the inside where you do focus and focus-within, and then you’ve got a couple of different child selectors. So this is probably the most challenging one that I get to work, but I think it is still quite good and I think it’s worth a go.
Okay, on to target.
This one’s a little bit easier and I absolutely love this one.
This is probably my favourite one.
And target can be used for CSS-only modals, which I think are absolutely fantastic, ’cause modals are really, really hard, and a lot of the times you have to download a whole library like jQuery UI or Bootstrap just for modals. So I really, really like that this target CSS selector is now official part of the spec.
2018 is when it became an official part of the spec. It’s been around a bit longer bit things take a little while before they’re unofficially accepted in.
So this is my CSS-only modal.
So this one actually only has CSS, so it’s… And you just click the button and up comes the modal. This one also doesn’t have any extra divs.
It doesn’t have a backdrop div or anything. It’s just using the target selector, as I’ll show you.
So it just has the modal class around it, so that’s got the backdrop of it.
It’s got the opacity zero so you can’t see it, z-index negative one so you can’t get to it, and then when it has the target activated on it, it’s then shown and it comes up.
So all the HTML is is it’s an a with the href of the ID, and then the ID is on that modal, and that’s how it all links up, which is really cool. I didn’t, I’ve got it in my example, but I didn’t put it here.
For accessibility, there is actually a new aria-modal tag which is really, really cool because it used to be really, really hard to put accessibility onto modals.
If you’ve seen my last talk at Web Directions, I talk about this quite a bit.
So it is starting to get a bit easier, which is good. So yeah, aria-modal equals true, fantastic. We can add this to modals now.
It doesn’t work in all screen readers yet, but yeah, definitely going in the right direction, which is cool.
So the pros to this one.
It’s supported in all browsers.
This one goes all the way back to IE9, which I think is really, really cool.
You don’t need a whole JS library just for the one component.
You’re just putting in a little bit of CSS. Not as much support in mobile browsers, and the main con I find here is that because you’re working with hrefs and links, it does modify your browser history.
People probably aren’t doing that as much as I do that, though.
I’m not 100% sure if this is ever gonna become a thing, but there is actually a HTML dialogue element for modals. It doesn’t really work all that well.
It’s not really well-supported.
So hopefully this becomes a thing one day and there’s more support and we, yeah, don’t have to worry about all this anymore. Checked.
These are probably the most popular ones are the checked hacks.
So these are the hacks where you use a radio button, a hidden radio button or a hidden checkbox to do really cool things.
If you were here for Sarah’s talk, she was doing a very, basically the same hack, but she was doing it to hide the normal checkbox and put a pretty one there instead, which a lot of websites do, which is really great.
These, but you can also get them to do really, really cool other things instead.
So I use them a lot for accordion menus.
So if you’ve seen a menu like this where things are expanding and contracting. I’ve also used them for mobile navigation menus coming out. Anything that kinda opens and closed, you can use a checkbox hack.
So instead of using jQuery UI or Bootstrap, things like that again, you can now use the checked selector, which is recently, yeah, it’s recently got, yeah, really good browser support. It’s been officially added in.
And you can use it here, again, this is my CSS-only checkbox hack.
But this one just uses, yeah, inputs and labels and checkbox things to open and close divs, which is pretty cool.
So again, this has really good browser support. That one had a checkbox so you can open and close as many as you like. You can also use radio buttons if you have a scenario where you just want one open at a time.
It doesn’t really work as well for nested inputs. So if you’ve got an input inside a label, it doesn’t, it’s really hard to get that one working, so that’s why I’ve got the inputs next to the labels for that one.
So here I’ve got, yeah, the input next to the labels, and then you’ve just gotta make sure your ID matches up with your for attribute and you’re, yeah, and you’re good to go.
This input, I’ve got it in there.
So this is the CSS.
So this include input, this is just a mix in. You can check out my code pan, and this is just the way to hide the input so that screen readers still read it and read it out and you can put some extra aria attributes on there to let them know, hey, this isn’t a real checkbox. This is a checkbox hack.
And then you use a checked attribute and just, yeah, open display block, open, close.
I’ve just got display none, display block.
You can do all sorts of cool things with heights and then you can use transitions and other bits and pieces. This is just a very basic example.
In the future, we might be using this one.
I’m not sure.
Nobody really uses this element, either.
It doesn’t have much support.
But this is the details summary element.
So this essentially would do the same thing as I just showed you.
It’s not really well-supported.
Haven’t managed to successfully style it.
But it is a cool native HTML element that you can click on it and it does open and show, which is really cool. So hopefully it gets better in the future and we can start using this one a bit more. This is a bit of a bonus round.
This is one that I didn’t make.
This was made a while ago.
An this is checkbox tic-tac-toe.
So you can play tic-tac-toe using only checkbox hacks, which I find pretty cool.
So I suggest checking it out.
That one’s been around for a while.
I’m pretty sure it only works in Firefox, so I’ve had to have Firefox opened on this one, which I don’t normally use, and I’m just hoping the rest of my demos will work, too. We’ll see how we go.
(sighs) Columns. Okay, so recently, there’s been a lot of talk about CSS grid.
Love CSS grid.
CSS grid is great.
Flexbox, also really great.
These are really great tools and really great CSS properties for laying out your page.
You know, get rid of all those floats and everything, which is really great.
There’s one, though, that kinda goes under the radar. It doesn’t have as many use cases as the other ones, but I still kind of like it and, you know, I kinda have a soft spot for it.
This is CSS columns.
What it does really well is it does masonary layout really well.
So masonary layout is like Pinterest where you have things and you have them in different height and you have these really nice white space rivers running through them.
If you try and do a masonary layout in something like Flexbox or grid, it tries to make everything the same height in the row or it makes it the native height and then you got really inconsistent rivers running through it.
I haven’t managed to successfully do anything in the masonary layout in those ones, but then I found columns and I thought that was a really good way to do it as opposed to downloading a big masonary library. Masonary libraries are quite cool.
They do a bit more than what I’m gonna show you. But if you just want something, a bit more of a basic layout, I really suggest give columns a look ’cause it’s super easy and super quick to set up.
So I’ve used this in real life.
I’ve used this, yeah, this one is broken on Firefox.
There we go.
I’ve used this one for things like testimonials. I’ve used this one for things like images.
If you just kinda wanna show something where the order doesn’t really matter ’cause it doesn’t really go through a normal order that we do normally where we’re doing rows and we’ve got a top row and we’ve got a main content and our sidebars and things that are most important at the bottom and then least important, most important at the top and stuff.
This one goes one, and then up to the next one, two to three, four to five to six, kind of puts them around randomly.
But if you’re just doing it for presentation and the order doesn’t matter, I think this is quite a nice way to lay things out. As you can see, the code is super simple.
You just put column count and how many columns you want. You put what sorta gap you want.
You can specify the widths of the columns.
This one just did it three of equal width, but you can specify that.
You have to put a lotta prefixes in this and make sure your order prefix are set up. Mine isn’t, so what its done is it hasn’t broken inside and it’s wrapped onto the next div.
But if the page break avoid was working, that would just be on this one and it would be kind of a complete div.
So it depends on your use case.
If you’ve got text, you might want it to wrap over to the next one. If you’ve got something like images, you probably want it to be separate and you’ll just make sure that break-inside avoid has all the right prefixes for all the browsers so you don’t get random things happening with your images. So, yeah, this is supported in all browsers, as well, as long as you put all your prefixes in there. I really like how easy this one is to make responsive because you just change how many columns it is per your breakpoints, so that’s super simple.
As I said, though, the main drawback here is that there’s no real flexibility. You can’t go, “I want this element there and I want that element there “and I want that element there.” You kinda gotta rearrange your DOM and it’s a bit of trial and error to get it to look exactly how you want.
But I do recommend giving it a go if you’ve got a scenario like that.
All right, so the last one I wanna talk about is CSS transitions.
So lots of transitions, lots of keyframes, yeah, lots of different options for getting things to animate as you interact with them.
So this is probably the most basic example, but it’s an example I use all the time and it’s an example I see all the time, so I thought I’d put it up here.
So this is just as you hover over an element, it changes colour, and it changes colour with just, I’ve just put a transition there of .3 seconds. So it doesn’t change transition too harshly. It’s got a little bit of a buffer there.
And that’s kind of what you want on elements that are doing things like changing colour or are things that are moving.
You don’t want them to move too fast.
You don’t want them to change too fast.
Otherwise your users are gonna be in a bit of shock. Another one I really like with buttons is I use it on active.
I do a transform of negative one pixels on the y-axis and then it kinda looks like you’re actually pushing a button, and you can put a bit of transition on that, too, which is quite fun.
So yeah, very, very simple code here.
You put your transition.
You put your what thing you wanna transition there. In this case, background colour.
You put how long it’s gonna last.
There are lots and lots of other options here. I won’t go into them, basically because I don’t know all of them. It can get quite complicated with kind of the graphs and how you transition things, but I find the defaults are pretty good.
I would avoid using transition-all.
You can get some really weird stuff happening if you use transition-all on a complicated element. They kinda move all over the place and things jump around and it’s not good.
It’s also not good for your performance in terms of CSS because it has to work out how to transition all the things. So it is supported in all browsers.
I will put a note here that if you have a background image and you’re changing the background image using CSS animations, there is a bug in Safari.
Safari does not handle this at all.
I’ve spend, yeah, many, many headaches trying to get these things working for Safari until I just give up and just turn off animations in Safari.
You just don’t get nice things anymore with, you know. You can kinda get around this if you wanna transition an image and have it as an SVG, you can do an inline SVG and then animate that, and that’s okay.
But if you’re trying to swap out two different background images in Safari, it doesn’t handle it.
The only con here is that it doesn’t work on everything, and it definitely doesn’t work on auto heights and auto widths.
So I always have a bit of a pain here when I’d really like a nice height transition, but it doesn’t handle it if it doesn’t know exactly what height you gotta give it. So you’ve kinda gotta start giving it fixed heights and fixed widths and transition nodes, and that does get a little bit fiddly.
But there’s still a lot of other cool things you can transition.
Another bonus round.
This one isn’t mine, but this is a…
This is another one of my favourite CSS hacks. So this is a CSS-only carousel.
So this uses nice transitions, as you can see. Oh, a bit janky there.
(laughs) To go between one to other.
This one uses some keyframes.
It uses some transforms.
It kinda hides things to the side and it brings it in. And then these little buttons here are just links. They’re just a tags with little Unicode dots in them. So yeah, instead of a carousel library, really recommend Googling CSS-only carousels. There’s a lot out there.
One favourite of mine uses radio buttons, and I really love those ones.
All right, so CSS can do all these great things, as we can see.
What can’t it do? Well, CSS, like Batman, has no parents.
There is no parent element in CSS.
It’s really, really sad.
But yeah, in general, they don’t work because you can’t go up a level. The other point here is accessibility.
Because we’re using HTML elements in a way that is not a native way that, you know, radio buttons aren’t supposed to do carousels. That’s not what they’re supposed to do.
They’re supposed to, you know, you’re supposed to just use them to input data. It can make a screen reader get quite confused. It’s like, what is this element? If you’ve hidden the element the wrong way using display none or visibility none, it has no idea what’s going on.
And so this is where you do need to make sure that you have the right aria attributes in there, and if there’s anything that is dynamically changing, so if something’s opening and closing, then we’ve also gotta give that information to the screen reader, as well.
So aria-expanded’s a good example of that.
So these are things like your accordion that’s opening and closed.
You want it to be false when it’s closed and true when it’s open.
“This is open.
The next thing you know you’re an Imba developer or you’re a React developer.
(laughs) Not that there’s anything wrong with that.
(audience claps) (laid-back music)