{"rowid": 283, "title": "CSS3 Patterns, Explained", "contents": "Many of you have probably seen my CSS3 patterns gallery. It became very popular throughout the year and it showed many web developers how powerful CSS3 gradients really are. But how many really understand how these patterns are created? The biggest benefit of CSS-generated backgrounds is that they can be modified directly within the style sheet. This benefit is void if we are just copying and pasting CSS code we don\u2019t understand. We may as well use a data URI instead.\n\nImportant note\n\nIn all the examples that follow, I\u2019ll be using gradients without a vendor prefix, for readability and brevity. However, you should keep in mind that in reality you need to use all the vendor prefixes (-moz-, -ms-, -o-, -webkit-) as no browser currently implements them without a prefix. Alternatively, you could use -prefix-free and have the current vendor prefix prepended at runtime, only when needed.\n\nThe syntax described here is the one that browsers currently implement. The specification has since changed, but no browser implements the changes yet. If you are interested in what is coming, I suggest you take a look at the dev version of the spec.\n\nIf you are not yet familiar with CSS gradients, you can read these excellent tutorials by John Allsopp and return here later, as in the rest of the article I assume you already know the CSS gradient basics:\n\n\n\tCSS3 Linear Gradients\n\tCSS3 Radial Gradients\n\n\nThe main idea\n\nI\u2019m sure most of you can imagine the background this code generates:\n\nbackground: linear-gradient(left, white 20%, #8b0 80%);\n\nIt\u2019s a simple gradient from one color to another that looks like this:\n\n See this example live\n\nAs you probably know, in this case the first 20% of the container\u2019s width is solid white and the last 20% is solid green. The other 60% is a smooth gradient between these colors. Let\u2019s try moving these color stops closer to each other:\n\nbackground: linear-gradient(left, white 30%, #8b0 70%);\n\n See this example live\n\nbackground: linear-gradient(left, white 40%, #8b0 60%);\n\n See this example live\n\nbackground: linear-gradient(left, white 50%, #8b0 50%);\n\n See this example live\n\nNotice how the gradient keeps shrinking and the solid color areas expanding, until there is no gradient any more in the last example. We can even adjust the position of these two color stops to control where each color abruptly changes into another:\n\nbackground: linear-gradient(left, white 30%, #8b0 30%);\n\n See this example live\n\nbackground: linear-gradient(left, white 90%, #8b0 90%);\n\n See this example live\n\nWhat you need to take away from these examples is that when two color stops are at the same position, there is no gradient, only solid colors. Even without going any further, this trick is useful for a number of different use cases like faux columns or the effect I wanted to achieve in my homepage or the -prefix-free page where the background is only shown on one side and hidden on the other:\n\n\n\nCombining with background-size\n\nWe can do wonders, however, if we combine this with the CSS3 background-size property:\n\nbackground: linear-gradient(left, white 50%, #8b0 50%);\nbackground-size: 100px 100px;\n\n See this example live\n\nAnd there it is. We just created the simplest of patterns: (vertical) stripes. We can remove the first parameter (left) or replace it with top and we\u2019ll get horizontal stripes. However, let\u2019s face it: Horizontal and vertical stripes are kinda boring. Most stripey backgrounds we see on the web are diagonal. So, let\u2019s try doing that.\n\nOur first attempt would be to change the angle of the gradient to something like 45deg. However, this results in an ugly pattern like this: \n\n See this example live\n\nBefore reading on, think for a second: why didn\u2019t this produce the desired result? Can you figure it out?\n\nThe reason is that the gradient angle rotates the gradient inside each tile, not the tiled background as a whole. However, didn\u2019t we have the same problem the first time we tried to create diagonal stripes with an image? And then we learned that every stripe has to be included twice, like so:\n\n\n\nSo, let\u2019s try to create that effect with CSS gradients. It\u2019s essentially what we tried before, but with more color stops:\n\nbackground: linear-gradient(45deg, white 25%,\n #8b0 25%, #8b0 50%, \n white 50%, white 75%, \n #8b0 75%);\nbackground-size:100px 100px;\n\n See this example live\n\nAnd there we have our stripes! An easy way to remember the order of the percentages and colors it is that you always have two of the same in succession, except the first and last color.\n\nNote: Firefox for Mac also needs an additional 100% color stop at the end of any pattern with more than two stops, like so: ..., white 75%, #8b0 75%, #8b0). The bug was reported in February 2011 and you can vote for it and track its progress at Bugzilla.\n\nUnfortunately, this is essentially a hack and we will realize that if we try to change the gradient angle to 60deg:\n\n See this example live\n\nNot that maintainable after all, eh? Luckily, CSS3 offers us another way of declaring such backgrounds, which not only helps this case but also results in much more concise code:\n\nbackground: repeating-linear-gradient(60deg, white, white 35px, #8b0 35px, #8b0 70px);\n\n See this example live\n\nIn this case, however, the size has to be declared in the color stop positions and not through background-size, since the gradient is supposed to cover the entire container. You might notice that the declared size is different from the one specified the previous way. This is because the size of the stripes is measured differently: in the first example we specify the dimensions of the tile itself; in the second, the width of the stripes (35px), which is measured diagonally.\n\nMultiple backgrounds\n\nUsing only one gradient you can create stripes and that\u2019s about it. There are a few more patterns you can create with just one gradient (linear or radial) but they are more or less boring and ugly. Almost every pattern in my gallery contains a number of different backgrounds. For example, let\u2019s create a polka dot pattern:\n\nbackground: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, black 10%) 50px 50px;\nbackground-size:100px 100px;\n\n See this example live\n\nNotice that the two gradients are almost the same image, but positioned differently to create the polka dot effect. The only difference between them is that the first (topmost) gradient has transparent instead of black. If it didn\u2019t have transparent regions, it would effectively be the same as having a single gradient, as the topmost gradient would obscure everything beneath it.\n\nThere is an issue with this background. Can you spot it?\n\nThis background will be fine for browsers that support CSS gradients but, for browsers that don\u2019t, it will be transparent as the whole declaration is ignored. We have two ways to provide a fallback, each for different use cases. We have to either declare another background before the gradient, like so:\n\nbackground: black;\nbackground: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, black 10%) 50px 50px;\nbackground-size:100px 100px;\n\nor declare each background property separately:\n\nbackground-color: black;\nbackground-image: radial-gradient(circle, white 10%, transparent 10%),\nradial-gradient(circle, white 10%, transparent 10%);\nbackground-size:100px 100px;\nbackground-position: 0 0, 50px 50px;\n\nThe vigilant among you will have noticed another change we made to our code in the last example: we altered the second gradient to have transparent regions as well. This way background-color serves a dual purpose: it sets both the fallback color and the background color of the polka dot pattern, so that we can change it with just one edit. Always strive to make code that can be modified with the least number of edits. You might think that it will never be changed in that way but, almost always, given enough time, you\u2019ll be proved wrong.\n\nWe can apply the exact same technique with linear gradients, in order to create checkerboard patterns out of right triangles:\n\nbackground-color: white;\nbackground-image: linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%), \nlinear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%);\nbackground-size:100px 100px;\nbackground-position: 0 0, 50px 50px;\n\n See this example live\n\nUsing the right units\n\nDon\u2019t use pixels for the sizes without any thought. In some cases, ems make much more sense. For example, when you want to make a lined paper background, you want the lines to actually follow the text. If you use pixels, you have to change the size every time you change font-size. If you set the background-size in ems, it will naturally follow the text and you will only have to update it if you change line-height.\n\nIs it possible?\n\nThe shapes that can be achieved with only one gradient are:\n\n\n\tstripes\n\tright triangles\n\tcircles and ellipses\n\tsemicircles and other shapes formed from slicing ellipses horizontally or vertically\n\n\nYou can combine several of them to create squares and rectangles (two right triangles put together), rhombi and other parallelograms (four right triangles), curves formed from parts of ellipses, and other shapes.\n\nJust because you can doesn\u2019t mean you should\n\nTechnically, anything can be crafted with these techniques. However, not every pattern is suitable for it. The main advantages of this technique are:\n\n\n\tno extra HTTP requests\n\tshort code\n\thuman-readable code (unlike data URIs) that can be changed without even leaving the CSS file.\n\n\nComplex patterns that require a large number of gradients are probably better left to SVG or bitmap images, since they negate almost every advantage of this technique:\n\n\n\tthey are not shorter\n\tthey are not really comprehensible \u2013 changing them requires much more effort than using an image editor\n\n\nThey still save an HTTP request, but so does a data URI.\n\nI have included some very complex patterns in my gallery, because even though I think they shouldn\u2019t be used in production (except under very exceptional conditions), understanding how they work and coding them helps somebody understand the technology in much more depth.\n\nAnother rule of thumb is that if your pattern needs shapes to obscure parts of other shapes, like in the star pattern or the yin yang pattern, then you probably shouldn\u2019t use it. In these patterns, changing the background color requires you to also change the color of these shapes, making edits very tedious.\n\nIf a certain pattern is not practicable with a reasonable amount of CSS, that doesn\u2019t mean you should resort to bitmap images. SVG is a very good alternative and is supported by all modern browsers.\n\nBrowser support\n\nCSS gradients are supported by Firefox 3.6+, Chrome 10+, Safari 5.1+ and Opera 11.60+ (linear gradients since Opera 11.10). Support is also coming in Internet Explorer when IE10 is released. You can get gradients in older WebKit versions (including most mobile browsers) by using the proprietary -webkit-gradient(), if you really need them.\n\nEpilogue\n\nI hope you find these techniques useful for your own designs. If you come up with a pattern that\u2019s very different from the ones already included, especially if it demonstrates a cool new technique, feel free to send a pull request to the github repo of the patterns gallery. Also, I\u2019m always fascinated to see my techniques put in practice, so if you made something cool and used CSS patterns, I\u2019d love to know about it!\n\nHappy holidays!", "year": "2011", "author": "Lea Verou", "author_slug": "leaverou", "published": "2011-12-16T00:00:00+00:00", "url": "https://24ways.org/2011/css3-patterns-explained/", "topic": "code"}