Gradient Repetition
Published 12 years, 5 months pastYesterday, I shared a test of repeating linear gradients and the madness they embody in various browsers. There were some suggestions for fixes both on the intertubes as well as the comments section of the post, so I should take a moment to explore the reasons for my post and test, and also what I would consider to be stable alternatives to the patterns I was creating.
Primarily the test was to find out how browsers handle repeating-linear-gradient()
. Badly, as it turns out, at least for many of them. Chrome is the worst; far worse than Safari, which I found fascinating. So I wasn’t actually posting in search of a way around those problems, though in re-reading the post I can see where that impression might have developed. I was actually running an experiment where my starting hypothesis was that repeating gradients were safe to use. This was proven to be false. (Science!) Having found out that there are glitches and inconsistencies that are sensitive to element size, and seeing how wildly, almost hilariously wrong some engines have gotten this, I came to the conclusion that repeating-linear-gradient()
isn’t yet ready for use.
That’s okay. Not everything in CSS is ready for use. Almost everything in CSS wasn’t ready for use, once upon a time. I think color
is the one property that was probably stable from the outset, and even that had its quirks in Netscape 4, albeit in the handling of unknown values. (color: inherit
resulted in a shade we lovingly referred to as “monkey-vomit green”.)
Now, as for useful alternatives to repeating-linear-gradient()
: the most obvious (as in traditional, as in boring) method is to create a PNG or other pixel image and use the various background-related properties. For example, given a desire to have a 5-on-5-off pattern (as seen in test #5), you could create a 10×10 PNG and then tile it something like this:
background-image: url(5on5off.png);
background-repeat: repeat-x;
background-position: bottom center;
background-size: 10px 10px;
The advantages here are that A) pixel images are about as safe as you get; and B) if you want to stretch the image vertically, you can do so without having to produce a new image.
A second alternative, only fractionally less safe but rather more efficient, is to replace the external PNG with a regular non-repeating linear gradient. I much prefer this to the suggestion of sizing and tiling a repeating gradient, because the test shows we can’t have any confidence in consistency with repeating gradients right now. (This is particularly true in Chrome, which is the worst with small repeated gradients.) Plain old non-repeating linear gradients, on the other hand, are predictable once you get the syntax right. Thus:
background-image: linear-gradient(left,
rgba(255,0,0,0.5) 0px,
rgba(255,0,0,0.5) 5px,
rgba(255,0,0,0) 5px,
rgba(255,0,0,0) 10px);
background-repeat: repeat-x;
background-position: bottom center;
background-size: 10px 10px;
…with, of course, the various vendor-prefixed versions of that first declaration blatted out by your favorite CSS preprocessor, framework, JavaScript shim, brain and fingers, or other tool of choice. The repeating pattern here is handled by the background-repeat
declaration instead of relying on repeating-linear-gradient()
to do it for you. It’s exactly the same as the first alternative except the pixel image has been replaced with a textually-described image.
So why do browsers not just do that internally? Well, I really don’t know, though it’s quite probable that performance plays an important role. For repetitions along the primary axes, they could certainly do it very easily. But the big advantage of repeating-linear-gradient()
, and the place where both alternatives can fall flat on their faces unless you are very careful, is in creating repeating patterns that don’t march on one of the primary axes. Repeating a static linear gradient along the X axis is fine as long as it’s perfectly perpendicular to the X axis, but what happens when you want to repeat a pattern that’s tilted 30 degrees?
Yes, this sort of effect can certainly be worked out by hand or tool — after all, we’ve seen those kinds of patterns done with GIFs and PNGs and the like for decades now — but it’s a lot harder to do. It’s still what I’d recommend right now, because having a reliably repeated background is usually far better than one whose rendering you can’t predict.
The goal of repeating-linear-gradient()
was to make it easy to specify a repeating pattern at any angle and not have to worry about the minutiae. Unfortunately, until rendering engines actually start properly handling the minutiae, we need to do it by hand if we do it at all.