Categories
Tips Tutorials

Hybrid positioning with CSS variables and max()

Notice how the navigation on the left behaves wrt scrolling: It’s like absolute at first that becomes fixed once the header scrolls out of the viewport.

One of my side projects these days is a color space agnostic color conversion & manipulation library, which I’m developing together with my husband, Chris Lilley (you can see a sneak peek of its docs above). He brings his color science expertise to the table, and I bring my JS & API design experience, so it’s a great match and I’m really excited about it! (if you’re serious about color and you’re building a tool or demo that would benefit from it contact me, we need as much early feedback on the API as we can get! )

For the documentation, I wanted to have the page navigation on the side (when there is enough space), right under the header when scrolled all the way to the top, but I wanted it to scroll with the page (as if it was absolutely positioned) until the header is out of view, and then stay at the top for the rest of the scrolling (as if it used fixed positioning).

Categories
Original Tips

Autoprefixing, with CSS variables!

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:

* {
	--clip-path: initial;
	-webkit-clip-path: var(--clip-path);
	clip-path: var(--clip-path);
}

Then, every time we need clip-path, we use –clip-path instead and it just works:

header {
	--clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 2.5em), 0% 100%);
}

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? 😉

Categories
Original Tips

Dynamically generated SVG through SASS + A 3D animated RGB cube!

Screenshot of the cubeToday, 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:

RGB cube sidesThese 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.

It seemed obvious that the best idea would be to use SVG background images. For example, here is the SVG background needed for the top left one:

<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px">

<linearGradient id="yellow-white" x1="0" x2="0" y1="0" y2="1">
	<stop stop-color="yellow" />
	<stop offset="1" stop-color="white" />
</linearGradient>
<linearGradient id="magenta-red" x1="0" x2="0" y1="0" y2="1">
	<stop stop-color="red" />
	<stop offset="1" stop-color="magenta" />
</linearGradient>
<linearGradient id="gradient" x1="0" x2="1" y1="0" y2="0">
	<stop stop-color="white" />
	<stop offset="1" stop-color="black" />
</linearGradient>
<mask id="gradient-mask">
	<rect width="100%" height="100%" fill="url(#gradient)"/>
</mask>

<rect width="100%" height="100%" fill="url(#yellow-white)"/>
<rect width="100%" height="100%" fill="url(#magenta-red)" mask="url(#gradient-mask)"/>

</svg>

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:

@function inline-svg($content, $width: $side, $height: $side) {
	@return url('data:image/svg+xml,#{$content}');
}

@function svg-rect($fill, $width: '100%', $height: $width, $x: '0', $y: '0') {
	@return unquote('');
}

@function svg-gradient($id, $color1, $color2, $x1: 0, $x2: 0, $y1: 0, $y2: 1) {
	@return unquote('

	');
}

@function svg-mask($id, $content) {
	@return unquote('#{$content}');
}

And then I was able to generate each RGB plane with another function that made use of them:

@function rgb-plane($c1, $c2, $c3, $c4) {
	@return inline-svg(
		svg-gradient('top', $c1, $c2) +
		svg-gradient('bottom', $c3, $c4) +
		svg-gradient('gradient', white, black, 0, 1, 0, 0) +
		svg-mask('gradient-mask', svg-rect('url(%23gradient)')) +
		svg-rect('url(%23bottom)') +
		svg-rect('url(%23top)" mask="url(%23gradient-mask)')
	);
}

/* ... */

.cube {
	background: rgb-plane(blue, black, aqua, lime);

	&::before {
		background: rgb-plane(blue, fuchsia, aqua, white);
	}

	&::after {
		background: rgb-plane(fuchsia, red, blue, black);
	}
}

.cube .sides {
	background: rgb-plane(yellow, lime, red, black);

	&::before {
		background: rgb-plane(yellow, white, red, fuchsia);
	}

	&::after {
		background: rgb-plane(white, aqua, yellow, lime);
	}
}

However, the same functions can be used for all sorts of SVG backgrounds and it’s very easy to add a new one. E.g. to make polygons:

@function svg-polygon($fill, $points) {
	@return unquote('');
}

@function svg-circle($fill, $r: '50%', $cx: '50%', $cy: '50%') {
	@return unquote('');
}

You can see the whole SCSS file here and its CSS output here.

Warning: Keep in mind that IE9 and some older versions of other browsers have issues with unencoded SVG data URIs. Also, you still need to escape hashes (%23 instead of #), otherwise Firefox fails.

Categories
Tips

Smooth state animations with animation-play-state

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.

Screenshot

Categories
Thoughts

CSS is for developers

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!

However, if I had to pick one role, I would definitely consider myself more of a developer than a designer. I discovered coding on my own when I was 12 and so far it has been the most long lasting love of my life. Although I lost my coding virginity to Visual Basic (something I’m still embarrassed about), over the years I’ve coded in Java, C, C++, C#, PHP, JavaScript before I even got to CSS. I’ve actually studied Computer Science at university, graduated 4th in my class and I’m gonna be doing research at MIT towards a PhD, starting fall 2014. Regarding design, I’m completely self-taught. My personality is more similar to the developers I know than the designers I know. Coding comes naturally, but I have to struggle to get better at design. I’m a better developer than I will ever be a designer.

Still, the assumption often is that I can’t possibly be a developer and interested in CSS, when there are all these amazing programming languages to focus my energy on instead. Therefore I must be a designer …right? There are even people who know about my open source projects, and still think that I can’t code in JavaScript or any other programming language (not sure how you can make most of these tools with pure CSS, but since CSS is Turing complete, I guess there must be a way!).

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).

This is no coincidence. The skills required to write good CSS code are by and large the same skills required to write good code in general. CSS code also needs to be DRY, maintainable, flexible etc. CSS might have a visual output, but is still code, just like SVG, WebGL/OpenGL or the JavaScript Canvas API. It still requires the same kind of analytical thinking that programming does. Especially these days that most people use preprocessors for their CSS, with variables, math, conditionals and loops, it’s almost starting to look like programming!

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! 😀

Categories
Tips

Cleanest CSS spinner, ever

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.

Enjoy 🙂

Ideas for further improvement are welcome. Remember that it’s not just the size of the code that matters, but also its simplicity.

Categories
Tips

Flexible Google-style loader with CSS

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: Google’s loader

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-left until 50% of the width and then border-right from 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 🙂

Categories
News

Can we get rid of gradient prefixes?

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:

  • Chrome 26+
  • Firefox 16+
  • Opera 12.10+
  • IE10+

Lets have a look at which prefixes we actually need to use for gradients today.

-ms-

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.

-moz-

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.

-o-

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.

-webkit-

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.

My opinion

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.

Categories
Tips

Use MathML today, with CSS fallback!

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.

As you may know, my slides are made with HTML, CSS & JavaScript. At some point, I wanted to insert an equation to show how border-top-left-radius (as an example) shrinks proportionally when the sum of radii on the top side exceeds the width of the element. I don’t like LaTeX because it produces bitmap images that don’t scale and is inaccessible. The obvious open standard to use was MathML, and it can even be directly embedded in HTML5 without all the XML cruft, just like SVG. I had never written MathML before, but after a bit of reading and poking around existing samples, I managed to write the following MathML code:

Categories
Original

iOS 6 switch style checkboxes with pure CSS

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:

  1. It should be keyboard accessible
  2. It should work in as many browsers as possible and degrade gracefully to a plain checkbox in the rest
  3. It shouldn’t depend on pseudo-elements in replaced elements (such as checkboxes), since that’s non-standard so not very dependable
  4. It shouldn’t require any extra HTML elements
  5. 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!).