Recently, when I was making the minisite for markapp.io, I realized a neat trick one can do with CSS variables, precisely due to their dynamic nature. Let’s say you want to use a property that has multiple versions: an unprefixed one and one or more prefixed ones. In this example we are going to use clip-path, which currently needs both an unprefixed version and a -webkit- prefixed one, however the technique works for any property and any number of prefixes or different property names, as long as the value is the same across all variations of the property name.
The first part is to define a --clip-path property on every element with a value of initial. This prevents the property from being inherited every time it’s used, and since the * has zero specificity, any declaration that uses --clip-path can override it. Then you define all variations of the property name with var(--clip-path) as their value:
Even !important should work, because it affects the cascading of CSS variables. Furthermore, if for some reason you want to explicitly set -webkit-clip-path, you can do that too, again because * has zero specificity. The main downside to this is that it limits browser support to the intersection of the support for the feature you are using and support for CSS Variables. However, all browsers except Edge support CSS variables, and Edge is working on it. I can’t see any other downsides to it (except having to use a different property name obvs), but if you do, let me know in the comments!
I think there’s still a lot to be discovered about cool uses of CSS variables. I wonder if there exists a variation of this technique to produce custom longhands, e.g. breaking box-shadow into --box-shadow-x, --box-shadow-y etc, but I can’t think of anything yet. Can you? 😉
Today, I was giving the opening keynote at Codemania in Auckland, New Zealand. It was a talk about color from a math/dev perspective. It went quite well, despite my complete lack of sleep. I mean that quite literally: I hadn’t slept all night. No, it wasn’t the jetlag or the nervousness that kept me up. It was my late minute decision to replace the static, low-res image of an RGB cube I was using until then with a 3D cube generated with CSS and animated with CSS animations. Next thing I knew, it was light outside and I had to start getting ready. However, I don’t regret literally losing sleep to make a slide that is only shown for 20 seconds at most. Not only it was super fun to develop, but also yielded a few things that I thought were interesting enough to blog about.
The most challenging part wasn’t actually the 3D cube. This has been done tons of times before, it was probably the most common demo for CSS 3D transforms a couple of years ago. The only part of this that could be of interest is that mine only used 2 elements for the cube. This is a dabblet of the cube, without any RGB gradients on it:
The challenging part was creating the gradients for the 6 sides. These are not plain gradients, as you can see below:
These are basically two linear gradients from left to right, with the topmost one being masked with a gradient from top to bottom. You can use CSS Masking to achieve this (for Chrome/Safari) and SVG Masks for Firefox, but this masks the whole element, which would hide the pseudo-elements needed for the sides. What I needed was masks applied to backgrounds only, not the whole element.
However, I didn’t want to have 6 separate SVG files, especially with this kind of repetition (cross-linking to reuse gradients and masks across different files is still fairly buggy in certain browsers). I wanted to be able to edit this straight from my CSS. And then it hit me: I was using SASS already. I could code SASS functions that generate SVG data URIs!
Here’s the set of SVG generating SASS functions I ended up writing:
When a CSS animation is applied from the beginning of the page load, things are easy. You just use the animation property with appropriate parameters, and you’re done. However, what if the animation is applied on a certain state, e.g. :hover, :active, :focus or a JS-triggered class change?
A naïve approach would be to try something like this:
However, this means that when you hover out of the element, it abruptly snaps to its original state (no rotation). In many cases, it would be a more desirable to have it freeze in the last shown frame, until we hover over it again. To achieve that, we can apply the animation from the beginning, with animation-play-state: paused; and just change it on :hover to animation-play-state: running;. This is what happens then:
I figured this out when I was recently helping my good friend Julian with his one page website*. When you hover over the figure, it starts scrolling, but when you hover out of it, it doesn’t snap back to its original position, which would’ve looked awful.
*Beware it’s still a bit rough around the edges, e.g. the result has some rendering bugs on Firefox & IE plus some unsupported features messing it up (e.g. baseline-shift in SVG), but those are for another day as I had work to do and this ended up taking longer than the few hours I expected. Beyond the animation, you might want to explore the CSS-only buttons (see what I did there?) or the leather figure frame. Credits to Laura Kalbag for the tweed background & color scheme. I also experimented with SASS on this one and found it much smoother to work with than LESS, so I might stick with it for those cases where I need a preprocessor.
Quite often people assume that because the language I focus on is CSS, I must be a web designer. Don’t get me wrong, I love visual design with a passion. I have studied it a lot over the years and I’ve worked on several design projects for clients. Heck, I even have a dribbble profile!
If you think I’m an exception, you’re mistaken. Everyone else in the W3C CSS Working Group, the group which defines the future of CSS, fits the profile of a developer much more than that of a designer. In fact, I might be the most designer-y person in it! Even outside the WG, the people I know who are really good at CSS, are either developers or hybrids (designers & developers).
I find it counter-productive that CSS in most jobs is assigned to designers. Designers should be doing what they do best and love: Design. Sure, they should be aware of the practical limitations of the medium and should be able to read and lightly edit CSS or hack together a prototype to show how their design behaves in different conditions, but it shouldn’t be their job to write CSS for production. The talents required to be a good designer and a good coder are very different and it’s unreasonable to expect both from everyone. Also, when you know you’re gonna have to implement the design you’re working on, it’s tempting to produce designs that can be easily converted to CSS, instead of pushing the boundaries. We don’t usually expect developers to design, even though it’s an added bonus when they have an eye for design as well. It should be the same for designers.
And if you’re a designer who writes amazing CSS and is about to tell me off in the comments, hold your horses. I’m not saying you shouldn’t be coding CSS. I’m saying that if you’re good at it, it means you’re both a designer AND a developer. Own it! 😀
For some reason, I seem to have a fascination with CSS loaders these days. After recreating the Google loader with clean CSS recently, I set off to recreate the classic spinner with CSS. Yes, I know this has been done zillions of times, but I wanted a clean, maintainable, reusable solution, not just a proof of concept. Something with not tons of CSS and/or HTML elements.
I managed to recreate it with only 2 elements. I’m still not completely satisfied, as I was hoping to come up with a solution with just one element, but it’s still much better than all those solutions out there that use tons of elements and code.
So, how did I do it?
I use the ::before and ::after pseudoelements of the parent and child div to create the 4 first bars
I use box-shadow with no blur on all four of the above to create the remaining 4 bars
I rotate the whole element with a steps(8) timing function to create the animation
As with the Google-style loader, just changing the font-size on this scales the whole element, as everything is sized with ems. Also, there is fallback text, to make it accessible to screen readers. Tested in Chrome, Firefox, Safari, IE10. Should degrade gracefully on IE9 (spinner should look fine, just no animation).
Using a preprocessor for variables and calculations should simplify the code even further.
Ideas for further improvement are welcome. Remember that it’s not just the size of the code that matters, but also its simplicity.
So, for a while I had noticed the nice sutble loader Google apps use and I was wondering if it would be easy to make with CSS and CSS animations:
Yesterday, I realised that you can get this effect by increasing border size until about the middle of the element, as long as the total width stays the same (by using box-sizing: border-box):
However, as you can see above, after the midpoint, the border is not curved any more, so does not produce the desired effect. However, what if we split the background colour in half, and animated border-leftuntil 50% of the width and then border-rightfrom 50% of the width? That worked, but only gave us 25% of the effect. I could recreate the whole effect by then animating border-top/bottom instead etc, but it’s easier to apply animation-direction: alternate to alternate between showing and hiding the circle and and simultaneously rotate the loader by 90deg each time, by applying animation-timing-function: steps(4) to a rotate animation that runs over 4x the duration of the border animation.
This is the finished result:
The dimensions are all set in ems so that you can change the size in one place: Just change the font-size and the loader scales perfectly. It’s also accessible to screen reader users, as there is still text there.
And yes, it’s not super useful as-is, there are tons of spinners on the Web that you can use instead. However, I decided to post it (instead of just tweeting it) as I thought the techniques involved in making it might be interesting for some of you 🙂
I recently realized that unprefixed gradients finally propagated to stable Chrome, and after tweeting about it, I decided to do some research on which browsers support unprefixed gradients, and what percentage of users needs them.
Currently, unprefixed gradients are supported in:
Lets have a look at which prefixes we actually need to use for gradients today.
There was never a stable release of IE that supported -ms- prefixed gradients, those were only in preview versions (stable IE10 supports both prefixed and unprefixed gradients). So, -ms- is most definitely not required.
Firefox versions >= 3.6 and < 16 account for 4% of the global user base*. This might or might not be significant, depending on how good the fallback is that these users will see. If the gradient only adds a subtle shadow or something like that, I’d say ditch -moz-. If it’s more crucial to the design & branding, it might be wise to still keep it. More tech-focused websites probably have a much lower percentage than 4%, so it might be a good idea to drop it there completely.
Opera unprefixed gradients in 12.10. Opera Mini never supported them. Opera versions < 12.10 currently account to a total of 0.25% of the global user base*. I’d say it’s safe to ditch -o- in gradients in most cases.
Chrome only very recently unprefixed gradients and Safari is a long way from doing so. Not to mention all the mobile browsers using WebKit. Unfortunately, we can’t ditch -webkit- in CSS gradients just yet.
Don’t use -ms- prefixed gradients, there’s absolutely zero point in doing so. Include -moz- for the less subtle gradients. No significant need for -o- gradients. -webkit- is still needed and probably will be at least until the end of 2013. Or, of course, just use -prefix-free and don’t bother. 😛
Keep in mind that your stats might differ from global stats, so which prefixes you need to include might differ on a case by case basis. The purpose of this post is to alert you that maybe you don’t need all these prefixes, not to prescriptively tell you which ones to keep. Except -ms-, please don’t use that. There’s absolutely zero reason whatsoever.
Last but not least, no matter which prefixes you include, always have a good solid color fallback!
* Global market share statistics from StatCounter, for a 3 month period of January 2013 – March 2013. The graph on the website only displays the most popular browser versions, but downloading the CSV file gives you all of them.
These days, I’m working on the slides for my next talk, “The humble border-radius”. It will be about how much work is put into CSS features that superficially look as simple as border-radius, as well as what advances are in store for it in CSS Backgrounds & Borders 4 (of which I’m an editor). It will be fantastic and you should come, but this post is not about my talk.
I recently found myself looking at the Tools switch in Espresso:
Not because I was going to use it (I rarely do), but because I started wondering what would be the best way to replicate this effect in CSS. I set on to create something that adhered to the following rules:
It should be keyboard accessible
It should work in as many browsers as possible and degrade gracefully to a plain checkbox in the rest
It shouldn’t depend on pseudo-elements in replaced elements (such as checkboxes), since that’s non-standard so not very dependable
It shouldn’t require any extra HTML elements
It shouldn’t use JS, unless perhaps to generate HTML that could be written by hand if the author wishes to do so.
Why you may ask? Some of them are good practices in general, and the rest make it easier to reuse the component (and they made it more challenging too!).
If you’ve used definition lists (<dl>) you’re aware of the problem. By default, <dt>s and <dd>s have display:block. In order to turn them into what we want in most cases (each pair of term and definition on one line) we usually employ a number of different techniques:
Using a different <dl> for each pair: Style dictating markup, which is bad
Floats: Not flexible
display: run-in; on the <dt>: Browser support is bad (No Firefox support)
Adding a <br> after each <dd> and setting both term and definition as display:inline: Invalid markup. Need I say more?
If only adding <br>s was valid… Or, even better, what if we could insert <br>s from CSS? Actually, we can!