Categories
Original Tips

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

Reading Time: 3 minutes

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
Original Releases

Preview corner-shape, before implementations!

Reading Time: 2 minutes

As an editor of the Backgrounds & Borders Level 4 spec, I am naturally a bit more interested in the cool features it will bring, once implementations start (it’s currently too early for that). One of the coolest features in it is corner-shape. While in Backgrounds & Borders 3, border-radius was only used for rounded (actually, elliptical) corners, with the help of corner-shape, it will be able to do so much more! Beveled corners, scoop-style corners (informally known as “negative border-radius”), even rectangular notches.

Unfortunately, until it’s implemented in browsers, it’s hard to play with it. Or, is it? I spent the weekend creating an app in which you can enter values for corner-shape, border-radius, width, and height, and see the result, simulated through SVG, as well as the fallback in browsers that don’t support border-corner-radius (which is currently all browsers).

corner-shape preview

Obviously, it’s not a full preview, since you can only play with a limited subset of CSS properties, but it should be good for seeing the kinds of shapes that will be possible.You could also copy the generated SVG from the Developer tools of your browser, and use it as a background in any website!

Use it here: corner-shape preview

Tested to work in at least Chrome, IE9, Firefox, Safari and theoretically, should work in any SVG-enabled browser.

Enjoy! Hope you like it.

Important: Please note that corner-shape is still at a very early stage and might completely change before implementations. You can also help to make it better: Play with it and comment on what you think about its naming and functionality!

Categories
Original Tips

Easily center text vertically, with SVG!

Reading Time: 2 minutes

These days, we have a number of different ways to vertically align text in a container of variable dimensions:

  • Table display modes
  • Flexbox
  • inline-block hacks
  • Wrapping the text in an extra element and absolutely positioning it
  • …and probably many others I’m forgetting

However, often comes a time when neither is suitable, so here I am, adding yet another option to the list. Of course, it comes with its own set of drawbacks, but there are cases where it might be better than the existing solutions.

Categories
Replies Tips

Text masking — The standards way

Reading Time: 2 minutes

As much as I like .net magazine, I was recently outraged by their “Texturizing Web Type” article. It features a way to apply a texture to text with -webkit-mask-image, presenting it as an experimental CSS property and misleading readers. There are even -moz-, -o- and -ms- prefixes for something that is not present in any specification, and is therefore unlikely to ever be supported by any non-WebKit browser, which further contributes to the misdirection. A while back, I wrote about how detrimental to our work and industry such proprietary features can be.

A common response to such complaints is that they are merely philosophical and who cares if the feature works right now and degrades gracefully. This argument could be valid for some cases, when the style is just a minor, gracefully degrading enhancement and no standards compliant alternative is present (for example, I’ve used ::-webkit-scrollbar styles myself). However, this is not the case here. We have had a standards compliant alternative for this for the past 11 years and it’s called SVG. It can also do much more than masking, if you give it a chance.

Categories
Benchmarks

CSS gradients are faster than SVG backgrounds

Reading Time: 2 minutes

Which is really sad, because SVG is awesome. It lets you do what CSS gradients do and much more, in quite a small filesize, as it’s just text too. However, the browser needs to generate a DOM for every SVG graphic, which results in sluggishness.

Here’s my test case

Mouse over the 2 divs. They both use a spotlight effect that’s dynamically updated according to the position of the mouse cursor. One of them does it with an SVG (through a data URI), the other one through a CSS radial gradient.

The test only works in Chrome, Firefox nightlies and perhaps IE10 (haven’t tested in Windows). Why? Because Opera doesn’t support radial gradients yet (however you can see how slow SVG is in it too), and Firefox before the nightlies used to have a bug with gradients in SVG through data URIs. Also, jsFiddle seems not to work in Webkit nightlies for some reason, but I’m too lazy right now to make a self-hosted test case.

Thanks a lot to Christian Krebs (lead developer of Opera Dragonfly) who inspired these tests after a discussion we had today regarding CSS gradient performance.

Edit: According to some commenters, they’re the same speed on Windows and Linux, so it could be an OSX issue. The only way to know for sure is to post more results, so go ahead and post yours!

Also, some commenters say that this is not a fair comparison, because it generates a new SVG every time. I have several arguments to reply to this:

  1. We also generate a new gradient every time, so it is fair.
  2. You can’t manipulate an SVG used for a background, so it’s not an option for backgrounds. JS doesn’t run in it and you don’t have access to its DOM. The only way to do that would be to use an inline SVG embedded in HTML and the element() CSS3 function. However, that’s only supported by Firefox, so not really a pragmatic option.
Categories
Original

CSS reflections for Firefox, with -moz-element() and SVG masks

Reading Time: 2 minutes

We all know about the proprietary (and imho, horrible) -webkit-box-reflect. However, you can create just as flexible reflections in Firefox as well, by utilizing -moz-element(), some CSS3 and Firefox’s capability to apply SVG effects to HTML elements. And all these are actually standards, so eventually, this will work in all browsers, unlike -webkit-box-reflect, which was never accepted by the CSS WG.

First and foremost, have a look at the demo:

How it works

  • For every element, we generate an ::after pseudoelement with the same dimensions and a position of being right below our original element.
  • Then, we make it appear the same as our element, by giving it a background of ‑moz-element(#element-id) and no content.
  • Reflections are flipped, so we flip it vertically, by applying transform: scaleY(‑1);
  • If we want the reflection to have a little distance from the element (for example 10px like the demo), we also apply a transform of translateY(10px)
  • We want the reflection to not be as opaque as the real element, so we give it an opacity of around 0.3-0.4
  • At this point, we already have a decent reflection, and we didn’t even need SVG masks yet. It’s essentially the same result -webkit-box-reflect gives if you don’t specify a mask image. However, to really make it look like a reflection, we apply a mask through an SVG and the mask CSS property. In this demo, the SVG is external, but it could be a data URI, or even embedded in the HTML.

Caveats

  • Won’t work with replaced elements (form controls, images etc).
  • If you have borders, it gets a bit more complicated to size it properly
  • Doesn’t degrade gracefully, you still get the pseudoelement in other browsers, so you need to filter it out yourself
  • Bad browser support (currently only Firefox 4+)
  • You need to set the reflection’s background for every element and every element needs an id to use it (but this could be done automatically via script)

Further reading

Credits: Thanks to Christian Heilmann for helping me debug why SVG masks for HTML elements weren’t originally working for me.

Categories
Articles Original Personal

Organizing a university course on modern Web development

Reading Time: 10 minutes

About a year ago, prof. Vasilis Vassalos of Athens University of Economics and Business approached me and asked for my help in a new course they were preparing for their Computer Science department, which would introduce 4th year undergrads to various web development aspects. Since I was always complaining about how outdated higher education is when it comes to web development, I saw it as my chance to help things change for the better, so I agreed without a second thought.

This is one of the main reasons I didn’t have time to write many blog posts for the past months: This activity took up all my spare time. However, it proved to be an interesting and enlightening experience, in more than one ways. In this blog post I’ll describe the dilemmas we faced, the decisions we made and the insights I gained throughout these 6 months, with the hope that they’ll prove to be useful for anyone involved in something similar.

Table of contents

  1. Content
  2. Homework
  3. Labs
  4. Personal aftermath

Categories
Rants Thoughts

“Wow, Mona Lisa with pure CSS!”

Reading Time: 2 minutes

There has been a recent flood of CSS experiments that utilize CSS3 features to convert some meaningless markup to spectacular pictures. It all started when David Desandro used CSS3 to draw the Opera logo. This seemed to inspire lots of other folks who created similar demos:

I can certainly share their enthusiasm and I am also amazed by their results. Besides that, I think that pushing CSS3 to the edge like that, helps us understand the spec better, which leads us to find and file browser bugs or write comments regarding the spec itself. Filing bugs is crucial at this stage, with all browser vendors gradually adding experimental –and frequently buggy– CSS3 support to their products. Also, don’t get me wrong: I can easily see the benefits of reducing the number of images in a web application interface (far quicker/easier modifications, less HTTP requests and most of the time, less bandwidth).

However, I’m afraid we’re losing sight of the big picture. These aren’t demos that are or will ever be legitimate CSS use cases. Even after universal CSS3 browser support is achieved, they would (and should) still be considered “hacks”. Almost all the arguments pro their usage also apply to more suitable ways of including images in web applications:

  • Fewer HTTP requests: Same with any kind of embedded image (data URIs, inline SVG and so on)
  • Scalable: Same with SVG and symbols embedded in custom fonts
  • Easier to modify: Same with SVG
  • Less bandwidth (in some cases): Same with SVG (and it can be cached too, when not inline)
And apart from these, these illustrations require non-semantic crap to be included in the markup which, besides issues of theoretical purity, makes it harder for other people to use them.
As for the graceful degradation argument, yes, this does only apply to CSS “images”. But in this case, is it really an advantage? I seriously doubt it. People won’t notice rounded corners if they’re missing from an interface, but they’re definitely going to notice a blocky Opera logo. And they’re not used in thinking that their browser has something to do with how an image renders, so they’ll just blame the website.

CSS is supposed to enhance the presentation of a document or interface, not to be (ab)used for the creation of illustrations from scratch. It’s supposed to separate presentation from structure, not generate stuff. There are other technologies that are far more suitable for this (*cough*SVG*cough*). I think we should use our energy and creativity to make CSS3 demos that people will actually use in the future when all this is fully supported, not stuff doomed to be eternally considered hackery.

“Where should we draw the line?” one might ask. For example, is a Pure CSS analog clock a CSS abuse case? Or even my own CSS iPhone keyboard? Now that’s a good question! A rule of thumb seems to be “if it inherently (=not due to browser support issues) involves a bunch of empty (or with meaningless content) HTML elements, then that’s a bad sign” but that might be overly strict. What’s your take on it?

Disclaimer: Yes, I’m fully aware that most of the time, such experiments are created just for fun by their (very talented) authors, which are perfectly aware of all the things mentioned above. However, I’ve also grown tired of reading comments by people that seem to to think that “This is the future of the web!”. Let’s hope it’s not.