Blog

38 posts 2009 16 posts 2010 50 posts 2011 28 posts 2012 15 posts 2013 7 posts 2014 10 posts 2015 5 posts 2016 4 posts 2017 7 posts 2018 2 posts 2019 17 posts 2020 7 posts 2021 7 posts 2022 11 posts 2023 6 posts 2024

Convert standard gradient syntax to -webkit-gradient and others

1 min read 0 comments Report broken page

Screenshot of the demoI hate -webkit-gradient() with a passion. Its syntax is cumbersome and itā€™s really limited: No angle support, no <length>s in color stop positions, no implied color stop positions, no elliptical gradientsā€¦ So, I was really happy, when Webkit implemented the standard syntax this January. However, weā€™re still stuck with the horrid -webkit-gradient() for quite a while, since older Webkit browsers that donā€™t support it are widely used at this time.

Today, I decided to finally spare myself the hassle of converting my standard gradient syntax to -webkit-gradient() by hand. Tasks like that shouldnā€™t be handled by a human. So, I coded a little script to do the chore. Hope it helps you too: View demo

It currently only supports linear gradients, but I plan to add radial ones in the future. Also, when I get around to cleaning up the code a bit, Iā€™ll add it on Github.

(Hope I didnā€™t leave in any very stupid bug, itā€™s really late here and Iā€™m half asleep.)


Beveled corners & negative border-radius with CSS3 gradients

1 min read 0 comments Report broken page

Just found out how to do beveled corners and simulate negative border radius without images, by utilizing CSS gradients once again. Itā€™s amazing how many CSS problems can be solved with gradients alone. Read the text in the dabblet below to find out how (or just check the code):

It also falls back to a solid color background if CSS gradients are not supported. It will work on Firefox 3.6+, Chrome, Safari, Opera 11.10+ and IE10+.

PS: For my twitter friends, I had already written this when the robbers came and I was about to post it. I might have been really calm, but not as much as making CSS experiments the same day I was robbed and threatened by a gun :P


On CSS preprocessors

4 min read 0 comments Report broken page

Lately there has been a rise in the usage of CSS preprocessors such as LESS and SASS, which makes sense given the simultaneous increase of CSS3 usage. Iā€™ve frequently argued with fellow front-end web developers about whether they should be used or not and I decided to finally put my thoughts in writing.

To start, I can fully understand the advantage of using such preprocessors over vanilla CSS3. I hate listing all the vendor prefixes, and not being able to use variables, mixins or nesting just like the next web developer. All this syntactic sugar can simplify your workflow by a great deal and make writing CSS3 incredibly fun. However, I still refrain from using them, and Iā€™ll explain why below.

Losing track of CSS filesize

When Iā€™m writing CSS, I try to keep the filesize as small as possible. Iā€™m not a filesize hypochondriac, I try to balance filesize and readability and I prefer to err on the side of the latter. Iā€™m not one of those people that will use #000 instead of black just to save a byte and I use lots of indents and newlines (later minification takes care of that). However, in cases when the readability impact is small and the filesize impact is large (and minification wonā€™t help), I will do the optimization.

For example, consider the following case: Letā€™s suppose you have 3 rules (#foo, #bar and #baz) that will both use the same CSS rotate transformation, among other CSS declarations. Using a mixin is simple (using the LESS syntax in this example):

.rotate (@degrees: 10deg) { -moz-transform: rotate(@degrees); -ms-transform: rotate(@degrees); -o-transform: rotate(@degrees); -webkit-transform: rotate(@degrees); transform: rotate(@degrees); }

#foo { font-size: 150%; .rotate(40deg); }

#bar { background: silver; .rotate(40deg); }

#baz { background: white; .rotate(40deg); }

Sweet, huh? And only 370 bytes. However, what the end user downloads is this beast:

#foo { font-size: 150%; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#bar { background: silver; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#baz { background: white; -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

which is almost double the filesize (600 bytes). It could have easily been this:

#foo, #bar, #baz { -moz-transform: rotate(40deg); -ms-transform: rotate(40deg); -o-transform: rotate(40deg); -webkit-transform: rotate(40deg); transform: rotate(40deg); }

#foo { font-size: 150%; }

#bar { background: silver; }

#baz { background: white; }

which at 290 bytes, is even smaller than the first one. The differences would be even bigger if you had to specify a different transform-origin.

Of course you can still do such optimizations when using CSS preprocessors, but since you donā€™t have the ugliness in front of you and the file youā€™re working with remains small, itā€™s easy to forget and just do whatā€™s easy. You lose sight of the big picture. But itā€™s the big picture (or big file, in this case ;)) that your users eventually download.

Same goes for nesting: Instead of actually putting some thought into the selectors you choose, you can just nest and let the preprocessor sort it out, usually in the straightforward but unavoidably verbose way.

LESS is better in this aspect, since it also offers a client-side version, so the user downloads the small file you wrote, and all the expansion is done in their machine. However, this has the (big, IMO) disadvantage that all your CSS becomes dependent on JavaScript to work and that your users have to download the LESS code, which isnā€™t that small: 33KB minified which is way larger than most stylesheets (granted, if you gzip, it will be smaller, but this is true for stylesheets as well).

Maintenance woes

Eventually, CSS will start supporting all this sweetness. Tab Atkins has already drafted a proposal and soon Webkit nightlies will implement the functionality. After that, I think itā€™s safe to assume that within 2 years Firefox and Opera will also implement the (by then) standard and within 1-2 more even IE. Then weā€™ll need another 2-3 years to be able to start using it (adoption rates of new browser versions will have increased too). This means that in as little as 6 years, we might be able to use CSS variables, mixins and nesting in vanilla CSS. All the code written for todayā€™s preprocessors will eventually have to be rewritten.Ā Maybe even sooner, since when a standard is published, I think itā€™s safe to assume (or hope) that the new versions of CSS preprocessors will deprecate their old syntax and start supporting and recommending the standard way, effectively becoming polyfills (which I definitely support). So, coding for a CSS preprocessor today feels a bit like building castles on sand.

Debugging woes (thanks to Jesper Ek)

Preprocessors make debugging CSS harder, since the CSS you see in Web Inspectors like Firebug or Dragonfly is not the CSS you wrote. The line numbers donā€™t match any more and the CSS itself is different. A lighter form of the same problem also occurs with minifiers, but you can delay using them until youā€™re done with the site. With CSS preprocessors, you have to use them from the beginning if you want to really take advantage of them.

Also, when I develop my CSS, I want to be able to instantly preview the changes in the file by just refreshing the browser. With preprocessors this becomes harder (although not impossible).

Generic concerns with such abstractions

With every new syntax, comes more effort required by someone to start working on our code. We either have to only collaborate with people proficient in the CSS preprocessor of our choice, or teach them its syntax. So we are either restricted in our choice of collaborators or need to spend extra time for training, both of which are nuisances.

Also, what happens if the preprocessor stops being updated? Granted, most (if not all) are open source, but the communityā€™s interest might shift to something else. Many open source projects have eventually died due to lack of interest. And letā€™s not forget the law of leaky abstractionsā€¦

Yes, both concerns are valid for every framework, in every language, but at least PHP frameworks or JavaScript libraries are more needed than CSS preprocessors, so itā€™s a tradeoff is thatā€™s worth it. For CSS preprocessors, Iā€™m not so sure.

Conclusion & disclaimer

I have to admit that even though Iā€™ve read quite a bit on CSS preprocessors and talked with fellow web developers about them, I donā€™t have hands-on experience with them. Maybe I will change my mind if I actually do so. Besides, I think that if someone uses a CSS preprocessor carefully, with knowledge of the points mentioned above, it can actually turn out to be beneficial. However personally, I prefer to wait at least until they start supporting the (future) standard syntax, whenever that happens.


WD @media talk subject change

1 min read 0 comments Report broken page

I recently changed my Web Directions @media talk title & abstract to something more specialized. Instead of discussing under-hyped CSS3 features in general I will only focus on one CSS3 feature (more hyped than the ones I was planning to show, but all the hype is only about very basic use cases): CSS3 Gradients:

Mastering CSS3 Gradients

With most browsers adding increasing support, and the simplicity of providing fallbacks for those that donā€™t, CSS3 gradients are something we can start to use right now. They benefit our users with faster websites and ourselves with more time in our hands to spend in other things, since they are easy to create, edit and update. A very powerful feature that can also be utilized for a surprising number of design effects, even ones that donā€™t resemble gradients at all. In this talk, Lea will explore CSS3 gradients in great depth and itā€™s almost guaranteed that no matter your expertise level, you will walk out having learned new things.

I tested a draft of this talk with a meetup group in Oslo (Framsia) and it went very well. I got reviews like ā€œI was amazed that you managed to speak almost an hour of CSS3 gradients and still keep the crowd interestedā€ (thanks Legendre!). Even Bruce Lawson, who happened to be there, told me he didnā€™t know like 70% of the material presented! :)

Iā€™m looking forward to it since itā€™s a topic Iā€™m passionate about, and I hope to see you there! Donā€™t forget that you can use the coupon code WDVEROU when registering to take Ā£50 off the current price.

PS: I donā€™t like the title very much, so if you have anything more witty to suggest, feel free. ;)


Custom &lt;select&gt; drop downs with CSS3

2 min read 0 comments Report broken page

The CSS3 Basic UI module defines pointer-events as:

The pointer-events property allows authors to control whether or when an element may be the target of user pointing device (pointer, e.g. mouse) events. This property is used to specify under which circumstance (if any) a pointer event should go ā€œthroughā€ an element and target whatever is ā€œunderneathā€ that element instead. This also applies to other ā€œhit testingā€ behaviors such as dynamic pseudo-classes (:hover, :active, :focus), hyperlinks, and Document.elementFromPoint().

The property was originally SVG-only, but eventually browsers and the W3C adopted a more limited version for HTML elements too.

It can be used in many use cases that werenā€™t possible before (or the solution was overly complicated), one of them being to create custom-looking <select> drop downs, by overlaying an element over the native drop down arrow (to create the custom one) and disallowing pointer events on it. Hereā€™s a quick example:

-webkit-appearance: none was needed in Webkit to turn off the native OSX appearance (in OSX and maybe Safari on Windows, I didnā€™t test that). However, since that also removes the native drop down arrow, our custom arrow now obscures part of the text, so we had to add a 30px padding-right to the select element, only in Webkit. You can easily detect if pointer-events is supported via JS and only apply this it if it is (eg by adding or removing a class from the body element):

if(!(ā€˜pointerEventsā€™ in document.body.style)) { ā€¦ }

However, there is one caveat in this: Opera does include pointerEvents in HTML elements as well, but it does not actually support the property on HTML. Thereā€™s a more elaborate feature detection script here as a Modernizr plugin (but the code is quite short, so you can adapt it to your needs).

Also, donā€™t try to replicate the behavior in JavaScript for browsers that donā€™t support this: itā€™s impossible to open a <select> drop down with JavaScript. Or, to put it differently, if you manage to do it, youā€™ll probably be the first to. Everything I could think of failed and I spent hours yesterday searching for a way, but no avail.

References


Checkerboard pattern with CSS3

1 min read 0 comments Report broken page

A while ago, I wrote a post on creating simple patterns with CSS3 gradients. A common pattern I was unable to create was that of a regular, non-rotated checkerboard. However, I noticed today that by giving a different background-position to every triangle in the pattern tile, a checkerboard can be easily created:

View in Gecko or Webkit. Webkit seems to have an odd rendering bug, so it needed a background-size override and it still doesnā€™t look perfect. Oh well, reported the bug and moved on.


Incrementable length values in text fields

1 min read 0 comments Report broken page

I always loved that Firebug and Dragonfly feature that allows you to increment or decrement a <length> value by pressing the up and down keyboard arrows when the caret is over it. I wished my Front Trends slides supported it in the editable examples, it would make presenting so much easier. So, I decided to implement the functionality, to use it in my next talk.

If you still have no idea what Iā€™m talking about, you can see a demo here: View demo

You may configure it so that it only does that when modifiers (alt, ctrl and/or shift) are used by providing a second argument to the constructor and/or change the units supported by filling in the third argument. However, bear in mind that holding down the Shift key will make it increment by Ā±10 instead of Ā±1 and thatā€™s not configurable (it would add too much unneeded complexity, Iā€™m not even sure whether itā€™s a good idea to make the other thing configurable either).

You may download it or fork it from itā€™s Github repo.

And if you feel creative, you may improve it by fixing an Opera bug I gave up on: When the down arrow is pressed, the caret moves to the end of the string, despite the code telling it not to.


Convert PHP serialized data to Unicode

1 min read 0 comments Report broken page

I recently had to convert a database of a large Greek website from single-byte Greek to Unicode (UTF-8). One of the problems I faced was the stored PHP serialized data: As PHP stores the length of the data (in bytes) inside the serialized string, the stored serialized strings could not be unserialized after the conversion.

I didnā€™t want anyone to go through the frustration I went through while searching for a solution, so here isĀ a little function I wrote to recount the string lengths, since I couldnā€™t find anything on this:

function recount_serialized_bytes($text) {
	mb_internal_encoding("UTF-8");
	mb_regex_encoding("UTF-8");

mb_ereg_search_init($text, ā€˜s:[0-9]+:"ā€™);

$offset = 0;

while(preg_match(ā€˜/s:([0-9]+):"/uā€™, $text, $matches, PREG_OFFSET_CAPTURE, $offset) || preg_match(ā€˜/s:([0-9]+):"/uā€™, $text, matches,PREGOFFSETCAPTURE,++offset)) { $number = $matches[1][0]; $pos = $matches[1][1];

digits = strlen(&quot;number"); poschars=mbstrlen(substr(text, 0, $pos)) + 2 + $digits;

str=mbsubstr(text, $pos_chars, $number);

newnumber=strlen(str); newdigits=strlen(new_number);

if($number != $new_number) { // Change stored number text=substrreplace(text, $new_number, $pos, $digits); $pos += $new_digits - $digits; }

$offset = $pos + 2 + $new_number; }

return $text; }

My initial approach was to do it with regular expressions, but the PHP serialized data format is not a regular language and cannot be properly parsed with regular expressions. All approaches fail on edge cases, and I had lots of edge cases in my data (I even had nested serialized strings!).

Note that this will only work when converting from single-byte encoded data, since it assumes the stored lengths are the string lengths in characters. Admittedly, itā€™s not my best code, it could be optimized in many ways. It was something I had to write quickly and was only going to be used by me in a one-time conversion process. However, it works smoothly and has been tested with lots of different serialized data. I know that not many people will find it useful, but itā€™s going to be a lifesaver for the few ones that need it.


Styling elements based on sibling count

1 min read 0 comments Report broken page

The original idea belongs to AndrƩ Luƭs, but I think it could be improved to be much less verbose.

AndrĆ©ā€™s solution is like this:

/* one item */
li:nth-child(1):nth-last-child(1) {
	width: 100%;
}

/* two items */ li:nth-child(1):nth-last-child(2), li:nth-child(2):nth-last-child(1) { width: 50%; }

/* three items */ li:nth-child(1):nth-last-child(3), li:nth-child(2):nth-last-child(2), li:nth-child(3):nth-last-child(1) { width: 33.3333%; }

/* four items */ li:nth-child(1):nth-last-child(4), li:nth-child(2):nth-last-child(3), li:nth-child(3):nth-last-child(2), li:nth-child(4):nth-last-child(1) { width: 25%; }

Itā€™s based on the relationship between :nth-child and :nth-last-child. As you can see, the number of total rules is O(N) and the number of selectors in every rule is also O(N).

However, what you really want, is to just target the first element. The others can be targeted with just a sibling selector. With my improvement, the number of total rules is still O(N), but the number of selectors in every rule becomes just 2, making this trick practical for far larger numbers of children:

/* one item */ li:first-child:nth-last-child(1) { width: 100%; }

/* two items */ li:first-child:nth-last-child(2), li:first-child:nth-last-child(2) ~ li { width: 50%; }

/* three items */ li:first-child:nth-last-child(3), li:first-child:nth-last-child(3) ~ li { width: 33.3333%; }

/* four items */ li:first-child:nth-last-child(4), li:first-child:nth-last-child(4) ~ li { width: 25%; }

And hereā€™s a fiddle to prove it:

Yes, I know that with Flexbox and the other layout modules, techniques such as these are soon becoming obsolete, but I think they are still useful right now. Iā€™m also aware that you can emulate this particular example with table display modes, but a) Table display modes have other implications that are sometimes undesirable and b) Widths are just an example, you could come up with other ways to style the elements based on their total count, which canā€™t be emulated by CSS tables.


I'm speaking at @media Web Directions ā€™11!

1 min read 0 comments Report broken page

Just a quick note to let you know Iā€™m speaking atĀ this yearā€™s @media Web Directions conference, which will take place during May 26ā€“27 in London, UK. Iā€™m very excited about this, since I always considered @media one of the top front-end conferences in the industry :)

The title and abstract of my talk is as follows:

CSS3 at the Outer Rim

By now most of you know how to use the core CSS3 features in your designs to embed custom fonts and easily create rounded corners, drop shadows, and scalable designs with media queries. But there is still a large area of CSS3 that remains unexplored by most web designers and developers. In this talk Lea will present many CSS3 features that are useful but underrated, as well as uncommon ways of utilising the CSS3 features you already know about, in order to do much more with even fewer images and less code.

Although itā€™s on the design track, I expect it to appeal to both developers and designers.

You can use the coupon code WDVEROU to take Ā£50 off the current price. ;)

Hope to see you there! :D


Yet another redesign

1 min read 0 comments Report broken page

I had grown sick of my previous blog style and its various bugs (since it was put together in just a few hours), so I decided to make a new, more minimalistic one. Best viewed in browsers that support CSS gradients, like Firefox, Safari and Chrome. I also finally got around to making a logo for myself, although Iā€™m not sure Iā€™ll keep it. I also switched to HTML5, using Toolbox as a base.

I want to make a few more changes, but I have to go to sleep sometime :p

I also started using DISQUS for the blog comments. I like it when a blog I read has it (since it offers a few features I find convenient, like comment editing for instance), so I wanted to offer it to my readers too.Ā Itā€™s a shame that in some of their buttons they havenā€™t added the standard CSS3 border-radius declarations, but only the prefixed proprietary ones, so theyā€™re square in Opera (and probably IE9). Iā€™m fed up with seeing this in websites, TOPSYā€™s widget also does it. However, their carelessness will backfire soon, when browsers stop supporting the prefixed versions *evil grin*


Checkerboard, striped & other background patterns with CSS3 gradients

2 min read 0 comments Report broken page

Screenshot of the CSS3 patterns I came up withYouā€™re probably familiar with CSS3 gradients by now, including the closer to the standard Mozilla syntax and the ugly verbose Webkit one. I assume you know how to add multiple color stops, make your gradients angled or create radial gradients. What you might not be aware of, is that CSS3 gradients can be used to create many kinds of commonly needed patterns, including checkered patterns, stripes and more.

View demo (Works in Webkit, Firefox 3.6+, Opera 11.50+ and IE10+)

The main idea behind the technique is the following, taken from the CSS3 Images spec:

If multiple color-stops have the same position, they produce an infinitesimal transition from the one specified first in the rule to the one specified last. In effect, the color suddenly changes at that position rather than smoothly transitioning.

I guess this makes it obvious how to create the tile for the stripes (unless youā€™ve never created a striped background before, but teaching you this is beyond the scope of this post). For example the gradient for the horizontal stripes is:

background-color: #0ae; background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(.5, rgba(255, 255, 255, .2)), color-stop(.5, transparent), to(transparent)); background-image: -moz-linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent); background-image: -o-linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent); background-image: linear-gradient(rgba(255, 255, 255, .2) 50%, transparent 50%, transparent);

Why transparent instead of the actual colors we want? For flexibility. background-color serves two purposes here: Setting the color of half the stripes and serving as a fallback for browsers that donā€™t support gradients.

However, without anything else, the tile will occupy the whole container. To control the size of each tile, you can use background-size:

-webkit-background-size: 50px 50px; -moz-background-size: 50px 50px; background-size: 50px 50px;

To create the picnic-style pattern, you just overlay horizontal stripes on vertical stripes.

The hardest one to figure out was the checkered pattern. It consists of two 45Ā° linear gradients and two -45Ā° linear gradients, each containing Ā¼ of the dark squares. I still havenā€™t managed to think of a way to create a regular checkerboard (not at 45Ā°) without needing an unacceptably large number of gradients. It will be very easily possible if conical gradients start being supported (currently theyā€™re not even in the spec yet).

Can you think of any other popular patterns that can be created with CSS3 and no images? If so, let me know with a comment. Cheers! :)

Added afterwards: Other patterns

There are far more pattern designs possible with CSS3 gradients than I originally thought. For more details, see this later post.


rgba.php v1.2: Improved URL syntax, now at Github

1 min read 0 comments Report broken page

I wrote the first version of rgba.php as a complement to an article on RGBA that I posted on Februrary 2009. Many people seemed to like the idea and started using it. With their valuable input, I made many changes and released v.1.1 (1.1.1 shortly after I posted the article due to another little fix) on October 2009. More than a year after, quite a lot of people still ask me about it and use it, so I decided to make a github repo for it and release a new version, with a much easier to use syntax for the URL, which lets you just copy and paste the color instead of rewriting it:

background: url(ā€˜rgba.php/rgba(255, 255, 255, 0.3)ā€™); background: rgba(255, 255, 255, 0.3);

instead of:

background: url(ā€˜rgba.php?r=255&g=255&b=255&a=30ā€™); background: rgba(255, 255, 255, 0.3);

I also made a quick about/demo page for it. Enjoy :)


Tag editing UIs

3 min read 0 comments Report broken page

I had to build the edit tags interface for an application Iā€™m working on, so I took a good look at how these are implemented across many popular applications nowadays. It seems there are a few patterns that are used over and over, and Iā€™m unsure which one is the most preferable by users, they all have their advantages and disadvantages. In this post Iā€™m going to describe these patterns and list some of the pros and cons I think they have. For simplicity, I will focus on the tag editing interface itself, ignoring any tag suggestions and other extra features.

Pattern #1: Input field to add new tags, delete button for existing ones

Used by: Wordpress, flickr, foursquareScreenshot of Wordpress' tagging UI

Pros:

  • One click deletion of tags

Cons:

  • Impossible to edit a tag, you have to remove it and add the corrected version
  • Hard to delete many tags at once
  • Disconnected new and existing tags, making it hard to get the bigger picture

foursquareā€™s implementation was the worst Iā€™ve tested: Thereā€™s no (discoverable?) way to delete or edit a tag and when you add one via the text field it doesnā€™t get cleared which is confusing because it makes it seem like an edit tags field although itā€™s an add tags field, as I found out the hard way (by creating a ā€œpizza, pastaā€ tag instead of 2 tags: pizza and pasta).

Pattern #2: One text field to edit, delete or add new tags

Used by: delicious, Google reader, stackoverflow, redditScreenshot of delicious' tagging UI

Pros:

  • Lets the user edit tags too, in addition to adding and deleting
  • Easy to delete many tags at once
  • All tags at one place

Cons:

  • More cumbersome to delete a tag
  • A bit more prone to mistakes than guided interfaces

Pattern #3: Hybrid approach: Text field for all, existing tags seem to be inside and have a delete button

Used by: last.fmScreenshot of last.fm's tagging UI

Pros:

  • All tags in one place
  • One click deletion
  • Easy to delete many tags too

Cons:

  • Thereā€™s no editing in last.fmā€™s implementation, but the pattern easily allows for that, for example by using contentEditable on the tag s

last.fm chooses to implement this by faking the tags being inside an input field: Technically theyā€™re implemented just like in pattern #1 above, with the difference that they visually appear to be inside the same box and every time a user inserts a comma (which is the tag separator) the tag they just typed is removed from the text field and a new link with a delete button is created just before the text field, which is much smaller than it looks.

Which pattern is the best?

As with most UI questions, I donā€™t think thereā€™s a definite answer to that. It heavily depends on the audience too: A more technically inclined user might be more comfortable with the 2nd approach since itā€™s the least restrictive one. The average casual internet user might prefer the 3rd approach. I donā€™t think thereā€™s any case where pattern #1 is better than pattern #3, except when development time is a concern (pattern #1 is a bit easier to implement, although #2 is the easiest of all).

Another pattern?

My initial attempt for the application Iā€™m building was to use a hybrid approach of #2 and #3: When the user clicked on ā€œEdit tagsā€, the tag container would get a contentEditable attribute and the idea was that every time a comma or any other non-permitted character would be inserted a new tag would be created (or if we were in the middle of one, it would get split into 2). That would have all the advantages of #2 and #3, except one-click deletion. It would also have the advantage that the user is directly editing the interface, which is usually a good idea usability-wise. I hate to admit I gave up on it for the time being, because it proved harder to implement than it seemed and I had to move on, so I went with #2. I might revisit it sometime in the future though if I still think itā€™s a good idea and nobody has done so by then.


The curious case of border-radius:50%

3 min read 0 comments Report broken page

Admittedly, percentages in border-radius are not one of the most common use cases. Some even consider them an edge case, since most people seem to set border-radius in pixels or --rarely-- ems. And since itā€™s not used very frequently, itā€™s still quite buggy. A bit of a chicken and egg case actually: Is it buggy because itā€™s used rarely or is it used rarely because itā€™s buggy? My vote would go to the first, so the purpose of this post is to let people know about why percentages in border-radius are incredibly useful and to highlight the various browser whims when it comes to rendering them.

Specification

Before we go into discussing implementations, letā€™s first examine what the right thing to do is, i.e. what the specification says:

Percentages: Refer to corresponding dimension of the border box.

The two length or percentage values of the ā€˜border-*-radiusā€™ properties define the radii of a quarter ellipse that defines the shape of the corner of the outer border edge (see the diagram below). The first value is the horizontal radius, the second the vertical radius. If the second value is omitted it is copied from the first. If either length is zero, the corner is square, not rounded. Percentages for the horizontal radius refer to the width of the border box, whereas percentages for the vertical radius refer to the height of the border box.

Why is that useful?

Itā€™s the only way of utilizing border-radius to draw a circle or ellipse, i.e. a rounded shape without any straight lines whatsoever (without knowing the dimensions in advance).

As you will see below, Firefox used to have a bug, or actually a different interpretation of the spec, which I think is a quite commonly needed use case, even more than ellipses: It always drew a regular curve for the corners (quarter of a circle) with the maximum possible radii. This is a very commonly needed shape in UI design. If youā€™re using OSX, youā€™re seeing it everywhere: the buttons, the scrollbars, even Skype (notice the blue or grey shading around the usernames in a chat). As Iā€™m writing this post, I can see the same shape in the buttons of Wordpressā€™ admin panel. And as the current spec stands, thereā€™s no way to do that. You have to know the height (or width, if you want a vertical shape) in advance, which even when possible, makes border-radius depend on the value of other attributes (such as line-height) and you have to remember to change it every time you change those, which causes maintenance headaches. And whatā€™s worse is that the Backgrounds & Borders module is almost done, so itā€™s quite unlikely that this will change anytime soon. :(

As noted inĀ this comment by David Baron, that assumption wasnā€™t exactly correct about Firefoxā€™s old rendering. It just resolved % as relative to width in every case (kinda like percentages in margins) and when the height was smaller than the width, it applied the rules for radii that are too big, which say to reduce it equally. A straightforward deduction is that we do have a standards-compliant way to get the behavior from old versions of Firefox, in every browser: Just specify a very big radius, like 9999px.

Different implementations, different bugs

Firefox 4 beta 6

As I mentioned above,Ā Gecko up to Firefox version 4 beta 6 always draws a regular curve for the corners with the largest radii applicable, resulting in a shape that is either a perfect circle or a rectangle with a semicircle on top and bottom (if height > width) or right and left (if width > height).

Minefield (latest Gecko nightlies)

In the latest nightlies this bug is fixed, and it follows the spec to the letter. I canā€™t help but wonder if this was a bug, a misinterpretation of the spec or a deliberate disagreement with it.

WebKit nightlies

Webkit was late to support percentages in border-radius, but it seems to be the first (it or IE9, Iā€™m not sure) to follow the spec to the letter --concerning corner radii at least-- and renders an ellipse (horizontal radius = width/2, vertical radius = height/2) no matter what. Webkit however seems to be having serious trouble with borders, rendering them with variable width strokes (!).

Opera 11

Presto (Opera) is the weirdest when it comes to rendering a percentage border-radius. I canā€™t figure out the algorithm it uses to determine the radii of the corners even if it was to save my life, it even changes according to window size in my testcases! Since Iā€™ve been using border-radius:50% regularly, Iā€™ve had the pleasure of observing Operaā€™s rendering in many different designs and I still canā€™t find a pattern. Itā€™s particularly funny when rendering the little fuchsia comment bubbles in the homepage of my blog: Every one of them has a different radius, even if they are about the same size. It even got one of them right and rendered it as an ellipse once!

Internet Explorer 9

Trident (IE9), along with the latest Gecko nightly is the only 100% correct one when it comes to rendering the testcases, which is not surprising since the IE team boasted quite a lot for their bulletproof border-radius implementation. Well, their CSS3 support might be a bit lacking, but at least the bits they actually implement arenā€™t buggy. Kudos for that.

Link to testcases

Note: Of course all bugs mentioned above have been reported to the respective browser vendors (except the Gecko one that is already fixed in the nightlies).