{"rowid": 54, "title": "Putting My Patterns through Their Paces", "contents": "Over the last few years, the conversation around responsive design has shifted subtly, focusing not on designing pages, but on patterns: understanding the small, reusable elements that comprise a larger design system. And given that many of those patterns are themselves responsive, learning to manage these small layout systems has become a big part of my work.\nThe thing is, the more pattern-driven work I do, the more I realize my design process has changed in a number of subtle, important ways. I suppose you might even say that pattern-driven design has, in a few ways, redesigned me.\nMeet the Teaser\nHere\u2019s a recent example. A few months ago, some friends and I redesigned The Toast. (It was a really, really fun project, and we learned a lot.) Each page of the site is, as you might guess, stitched together from a host of tiny, reusable patterns. Some of them, like the search form and footer, are fairly unique, and used once per page; others are used more liberally, and built for reuse. The most prevalent example of these more generic patterns is the teaser, which is classed as, uh, .teaser. (Look, I never said I was especially clever.)\nIn its simplest form, a teaser contains a headline, which links to an article:\n\nFairly straightforward, sure. But it\u2019s just the foundation: from there, teasers can have a byline, a description, a thumbnail, and a comment count. In other words, we have a basic building block (.teaser) that contains a few discrete content types \u2013 some required, some not. In fact, very few of those pieces need to be present; to qualify as a teaser, all we really need is a link and a headline. But by adding more elements, we can build slight variations of our teaser, and make it much, much more versatile.\n\n Nearly every element visible on this page is built out of our generic \u201cteaser\u201d pattern.\n \nBut the teaser variation I\u2019d like to call out is the one that appears on The Toast\u2019s homepage, on search results or on section fronts. In the main content area, each teaser in the list features larger images, as well as an interesting visual treatment: the byline and comment count were the most prominent elements within each teaser, appearing above the headline.\n\n The approved visual design of our teaser, as it appears on lists on the homepage and the section fronts.\n \nAnd this is, as it happens, the teaser variation that gave me pause. Back in the old days \u2013 you know, like six months ago \u2013 I probably would\u2019ve marked this module up to match the design. In other words, I would\u2019ve looked at the module\u2019s visual hierarchy (metadata up top, headline and content below) and written the following HTML:\n
\n

By Author Name

\n 126 comments\n

Article Title

\n

Lorem ipsum dolor sit amet, consectetur\u2026

\n
\nBut then I caught myself, and realized this wasn\u2019t the best approach.\nMoving Beyond Layout\nSince I\u2019ve started working responsively, there\u2019s a question I work into every step of my design process. Whether I\u2019m working in Sketch, CSSing a thing, or researching a project, I try to constantly ask myself:\n\nWhat if someone doesn\u2019t browse the web like I do?\n\n\u2026Okay, that doesn\u2019t seem especially fancy. (And maybe you came here for fancy.) But as straightforward as that question might seem, it\u2019s been invaluable to so many aspects of my practice. If I\u2019m working on a widescreen layout, that question helps me remember the constraints of the small screen; if I\u2019m working on an interface that has some enhancements for touch, it helps me consider other input modes as I work. It\u2019s also helpful as a reminder that many might not see the screen the same way I do, and that accessibility (in all its forms) should be a throughline for our work on the web.\nAnd that last point, thankfully, was what caught me here. While having the byline and comment count at the top was a lovely visual treatment, it made for a terrible content hierarchy. For example, it\u2019d be a little weird if the page was being read aloud in a speaking browser: the name of the author and the number of comments would be read aloud before the title of the article with which they\u2019re associated.\nThat\u2019s why I find it\u2019s helpful to begin designing a pattern\u2019s hierarchy before its layout: to move past the visual presentation in front of me, and focus on the underlying content I\u2019m trying to support. In other words, if someone\u2019s encountering my design without the CSS I\u2019ve written, what should their experience be?\nSo I took a step back, and came up with a different approach:\n
\n

Article Title

\n

By Author Name

\n

\n Lorem ipsum dolor sit amet, consectetur\u2026\n 126 comments\n

\n
\nMuch, much better. This felt like a better match for the content I was designing: the headline \u2013 easily most important element \u2013 was at the top, followed by the author\u2019s name and an excerpt. And while the comment count is visually the most prominent element in the teaser, I decided it was hierarchically the least critical: that\u2019s why it\u2019s at the very end of the excerpt, the last element within our teaser. And with some light styling, we\u2019ve got a respectable-looking hierarchy in place:\n\nYeah, you\u2019re right \u2013 it\u2019s not our final design. But from this basic-looking foundation, we can layer on a bit more complexity. First, we\u2019ll bolster the markup with an extra element around our title and byline:\n
\n
\n

Article Title

\n \n
\n \u2026\n
\nWith that in place, we can use flexbox to tweak our layout, like so:\n.teaser-hed {\n display: flex;\n flex-direction: column-reverse;\n}\nflex-direction: column-reverse acts a bit like a change in gravity within our teaser-hed element, vertically swapping its two children.\n\nGetting closer! But as great as flexbox is, it doesn\u2019t do anything for elements outside our container, like our little comment count, which is, as you\u2019ve probably noticed, still stranded at the very bottom of our teaser.\nFlexbox is, as you might already know, wonderful! And while it enjoys incredibly broad support, there are enough implementations of old versions of Flexbox (in addition to plenty of bugs) that I tend to use a feature test to check if the browser\u2019s using a sufficiently modern version of flexbox. Here\u2019s the one we used:\nvar doc = document.body || document.documentElement;\nvar style = doc.style;\n\nif ( style.webkitFlexWrap == '' ||\n style.msFlexWrap == '' ||\n style.flexWrap == '' ) {\n doc.className += \" supports-flex\";\n}\nEagle-eyed readers will note we could have used @supports feature queries to ask browsers if they support certain CSS properties, removing the JavaScript dependency. But since we wanted to serve the layout to IE we opted to write a little question in JavaScript, asking the browser if it supports flex-wrap, a property used elsewhere in the design. If the browser passes the test, then a class of supports-flex gets applied to our html element. And with that class in place, we can safely quarantine our flexbox-enabled layout from less-capable browsers, and finish our teaser\u2019s design:\n.supports-flex .teaser-hed {\n display: flex;\n flex-direction: column-reverse;\n}\n.supports-flex .teaser .comment-count {\n position: absolute;\n right: 0;\n top: 1.1em;\n}\nIf the supports-flex class is present, we can apply our flexbox layout to the title area, sure \u2013 but we can also safely use absolute positioning to pull our comment count out of its default position, and anchor it to the top right of our teaser. In other words, the browsers that don\u2019t meet our threshold for our advanced styles are left with an attractive design that matches our HTML\u2019s content hierarchy; but the ones that pass our test receive the finished, final design.\n\nAnd with that, our teaser\u2019s complete.\nDiving Into Device-Agnostic Design\nThis is, admittedly, a pretty modest application of flexbox. (For some truly next-level work, I\u2019d recommend Heydon Pickering\u2019s \u201cFlexbox Grid Finesse\u201d, or anything Zoe Mickley Gillenwater publishes.) And for such a simple module, you might feel like this is, well, quite a bit of work. And you\u2019d be right! In fact, it\u2019s not one layout, but two: a lightly styled content hierarchy served to everyone, with the finished design served conditionally to the browsers that can successfully implement it. But I\u2019ve found that thinking about my design as existing in broad experience tiers \u2013 in layers \u2013 is one of the best ways of designing for the modern web. And what\u2019s more, it works not just for simple modules like our teaser, but for more complex or interactive patterns as well.\nOpen video\n \n Even a simple search form can be conditionally enhanced, given a little layered thinking.\n \nThis more layered approach to interface design isn\u2019t a new one, mind you: it\u2019s been championed by everyone from Filament Group to the BBC. And with all the challenges we keep uncovering, a more device-agnostic approach is one of the best ways I\u2019ve found to practice responsive design. As Trent Walton once wrote,\n\nLike cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web\u2019s inherent variability.\n\nWe have a weird job, working on the web. We\u2019re designing for the latest mobile devices, sure, but we\u2019re increasingly aware that our definition of \u201csmartphone\u201d is much too narrow. Browsers have started appearing on our wrists and in our cars\u2019 dashboards, but much of the world\u2019s mobile data flows over sub-3G networks. After all, the web\u2019s evolution has never been charted along a straight line: it\u2019s simultaneously getting slower and faster, with devices new and old coming online every day. With all the challenges in front of us, including many we don\u2019t yet know about, a more device-agnostic, more layered design process can better prepare our patterns \u2013 and ourselves \u2013 for the future.\n(It won\u2019t help you get enough to eat at holiday parties, though.)", "year": "2015", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2015-12-10T00:00:00+00:00", "url": "https://24ways.org/2015/putting-my-patterns-through-their-paces/", "topic": "code"} {"rowid": 162, "title": "Conditional Love", "contents": "\u201cBrowser.\u201d The four-letter word of web design.\n\nI mean, let\u2019s face it: on the good days, when things just work in your target browsers, it\u2019s marvelous. The air smells sweeter, birds\u2019 songs sound more melodious, and both your design and your code are looking sharp.\n\nBut on the less-than-good days (which is, frankly, most of them), you\u2019re compelled to tie up all your browsers in a sack, heave them into the nearest river, and start designing all-imagemap websites. We all play favorites, after all: some will swear by Firefox, Opera fans are allegedly legion, and others still will frown upon anything less than the latest WebKit nightly.\n\nThankfully, we do have an out for those little inconsistencies that crop up when dealing with cross-browser testing: CSS patches.\n\nSpare the Rod, Hack the Browser\n\nBefore committing browsercide over some rendering bug, a designer will typically reach for a snippet of CSS fix the faulty browser. Historically referred to as \u201chacks,\u201d I prefer Dan Cederholm\u2019s more client-friendly alternative, \u201cpatches\u201d.\n\nBut whatever you call them, CSS patches all work along the same principle: supply the proper property value to the good browsers, while giving higher maintenance other browsers an incorrect value that their frustrating idiosyncratic rendering engine can understand.\n\nTraditionally, this has been done either by exploiting incomplete CSS support:\n\n#content {\n\theight: 1%;\t // Let's force hasLayout for old versions of IE.\n\tline-height: 1.6;\n\tpadding: 1em;\n}\nhtml>body #content {\n\theight: auto; // Modern browsers get a proper height value.\n}\n\nor by exploiting bugs in their rendering engine to deliver alternate style rules:\n\n#content p {\n\tfont-size: .8em;\n\t/* Hide from Mac IE5 \\*/\n\tfont-size: .9em;\n\t/* End hiding from Mac IE5 */\n}\n\nWe\u2019ve even used these exploits to serve up whole stylesheets altogether:\n\n@import url(\"core.css\");\n@media tty {\n\ti{content:\"\\\";/*\" \"*/}} @import 'windows-ie5.css'; /*\";}\n}/* */\n\nThe list goes on, and on, and on. For every browser, for every bug, there\u2019s a patch available to fix some rendering bug.\n\nBut after some time working with standards-based layouts, I\u2019ve found that CSS patches, as we\u2019ve traditionally used them, become increasingly difficult to maintain. As stylesheets are modified over the course of a site\u2019s lifetime, inline fixes we\u2019ve written may become obsolete, making them difficult to find, update, or prune out of our CSS. A good patch requires a constant gardener to ensure that it adds more than just bloat to a stylesheet, and inline patches can be very hard to weed out of a decently sized CSS file.\n\nGiving the Kids Separate Rooms\n\nSince I joined Airbag Industries earlier this year, every project we\u2019ve worked on has this in the head of its templates:\n\n\n\n\n\nThe first element is, simply enough, a link element that points to the project\u2019s main CSS file. No patches, no hacks: just pure, modern browser-friendly style rules. Which, nine times out of ten, will net you a design that looks like spilled eggnog in various versions of Internet Explorer.\n\nBut don\u2019t reach for the mulled wine quite yet. Immediately after, we\u2019ve got a brace of conditional comments wrapped around two other link elements. These odd-looking comments allow us to selectively serve up additional stylesheets just to the version of IE that needs them. We\u2019ve got one for IE 6 and below:\n\n\n\nAnd another for IE7 and above:\n\n\n\nMicrosoft\u2019s conditional comments aren\u2019t exactly new, but they can be a valuable alternative to cooking CSS patches directly into a master stylesheet. And though they\u2019re not a W3C-approved markup structure, I think they\u2019re just brilliant because they innovate within the spec: non-IE devices will assume that the comments are just that, and ignore the markup altogether.\n\nThis does, of course, mean that there\u2019s a little extra markup in the head of our documents. But this approach can seriously cut down on the unnecessary patches served up to the browsers that don\u2019t need them. Namely, we no longer have to write rules like this in our main stylesheet:\n\n#content {\n\theight: 1%;\t// Let's force hasLayout for old versions of IE.\n\tline-height: 1.6;\n\tpadding: 1em;\n}\nhtml>body #content {\n\theight: auto;\t// Modern browsers get a proper height value.\n}\n\nRather, we can simply write an un-patched rule in our core stylesheet:\n\n#content {\n\tline-height: 1.6;\n\tpadding: 1em;\n}\n\nAnd now, our patch for older versions of IE goes in\u2014you guessed it\u2014the stylesheet for older versions of IE:\n\n#content {\n\theight: 1%;\n}\n\nThe hasLayout patch is applied, our design\u2019s repaired, and\u2014most importantly\u2014the patch is only seen by the browser that needs it. The \u201cgood\u201d browsers don\u2019t have to incur any added stylesheet weight from our IE patches, and Internet Explorer gets the conditional love it deserves.\n\nMost importantly, this \u201ccompartmentalized\u201d approach to CSS patching makes it much easier for me to patch and maintain the fixes applied to a particular browser. If I need to track down a bug for IE7, I don\u2019t need to scroll through dozens or hundreds of rules in my core stylesheet: instead, I just open the considerably slimmer IE7-specific patch file, make my edits, and move right along.\n\nEven Good Children Misbehave\n\nWhile IE may occupy the bulk of our debugging time, there\u2019s no denying that other popular, modern browsers will occasionally disagree on how certain bits of CSS should be rendered. But without something as, well, pimp as conditional comments at our disposal, how do we bring the so-called \u201cgood browsers\u201d back in line with our design?\n\nAssuming you\u2019re loving the \u201cone patch file per browser\u201d model as much as I do, there\u2019s just one alternative: JavaScript.\n\nfunction isSaf() {\n\tvar isSaf = (document.childNodes && !document.all && !navigator.taintEnabled && !navigator.accentColorName) ? true : false;\n\treturn isSaf;\n}\nfunction isOp() {\n\tvar isOp = (window.opera) ? true : false;\n\treturn isOp;\n}\n\nInstead of relying on dotcom-era tactics of parsing the browser\u2019s user-agent string, we\u2019re testing here for support for various DOM objects, whose presence or absence we can use to reasonably infer the browser we\u2019re looking at. So running the isOp() function, for example, will test for Opera\u2019s proprietary window.opera object, and thereby accurately tell you if your user\u2019s running Norway\u2019s finest browser.\n\nWith scripts such as isOp() and isSaf() in place, you can then reasonably test which browser\u2019s viewing your content, and insert additional link elements as needed.\n\nfunction loadPatches(dir) {\n\tif (document.getElementsByTagName() && document.createElement()) {\n\t\tvar head = document.getElementsByTagName(\"head\")[0];\n\t\tif (head) {\n\t\t\tvar css = new Array();\n\t\t\tif (isSaf()) {\n\t\t\t\tcss.push(\"saf.css\");\n\t\t\t} else if (isOp()) {\n\t\t\t\tcss.push(\"opera.css\");\n\t\t\t}\n\t\t\tif (css.length) {\n\t\t\t\tvar link = document.createElement(\"link\");\n\t\t\t\tlink.setAttribute(\"rel\", \"stylesheet\");\n\t\t\t\tlink.setAttribute(\"type\", \"text/css\");\n\t\t\t\tlink.setAttribute(\"media\", \"screen, projection\");\n\t\t\t\tfor (var i = 0; i < css.length; i++) {\n\t\t\t\t\tvar tag = link.cloneNode(true);\n\t\t\t\t\ttag.setAttribute(\"href\", dir + css[0]);\n\t\t\t\t\thead.appendChild(tag);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nHere, we\u2019re testing the results of isSaf() and isOp(), one after the other. For each function that returns true, then the name of a new stylesheet is added to the oh-so-cleverly named css array. Then, for each entry in css, we create a new link element, point it at our patch file, and insert it into the head of our template.\n\nFire it up using your favorite onload or DOMContentLoaded function, and you\u2019re good to go.\n\nScripteat Emptor\n\nAt this point, some of the audience\u2019s more conscientious \u2018scripters may be preparing to lob figgy pudding at this author\u2019s head. And that\u2019s perfectly understandable; relying on JavaScript to patch CSS chafes a bit against the normally clean separation we have between our pages\u2019 content, presentation, and behavior layers.\n\nAnd beyond the philosophical concerns, this approach comes with a few technical caveats attached:\n\nBrowser detection? So un-133t.\n\nBrowser detection is not something I\u2019d typically recommend. Whenever possible, a proper DOM script should check for the support of a given object or method, rather than the device with which your users view your content.\n\nIt\u2019s JavaScript, so don\u2019t count on it being available.\n\nAccording to one site, roughly four percent of Internet users don\u2019t have JavaScript enabled. Your site\u2019s stats might be higher or lower than this number, but still: don\u2019t expect that every member of your audience will see these additional stylesheets, and ensure that your content\u2019s still accessible with JS turned off.\n\nBe a constant gardener.\n\nThe sample isSaf() and isOp() functions I\u2019ve written will tell you if the user\u2019s browser is Safari or Opera. As a result, stylesheets written to patch issues in an old browser may break when later releases repair the relevant CSS bugs.\n\nYou can, of course, add logic to these simple little scripts to serve up version-specific stylesheets, but that way madness may lie. In any event, test your work vigorously, and keep testing it when new versions of the targeted browsers come out. Make sure that a patch written today doesn\u2019t become a bug tomorrow.\n\nPatching Firefox, Opera, and Safari isn\u2019t something I\u2019ve had to do frequently: still, there have been occasions where the above script\u2019s come in handy. Between conditional comments, careful CSS auditing, and some judicious JavaScript, browser-based bugs can be handled with near-surgical precision.\n\nSo pass the \u2018nog. It\u2019s patchin\u2019 time.", "year": "2007", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2007-12-15T00:00:00+00:00", "url": "https://24ways.org/2007/conditional-love/", "topic": "code"} {"rowid": 238, "title": "Everything You Wanted To Know About Gradients (And a Few Things You Didn\u2019t)", "contents": "Hello. I am here to discuss CSS3 gradients. Because, let\u2019s face it, what the web really needed was more gradients.\n\nStill, despite their widespread use (or is it overuse?), the smartly applied gradient can be a valuable contributor to a designer\u2019s vocabulary. There\u2019s always been a tension between the inherently two-dimensional nature of our medium, and our desire for more intensity, more depth in our designs. And a gradient can evoke so much: the splay of light across your desk, the slow decrease in volume toward the end of your favorite song, the sunset after a long day. When properly applied, graded colors bring a much needed softness to our work.\n\nOf course, that whole \u2018proper application\u2019 thing is the tricky bit.\n\nBut given their place in our toolkit and their prominence online, it really is heartening to see we can create gradients directly with CSS. They\u2019re part of the draft images module, and implemented in two of the major rendering engines.\n\nStill, I\u2019ve always found CSS gradients to be one of the more confusing aspects of CSS3. So if you\u2019ll indulge me, let\u2019s take a quick look at how to create CSS gradients\u2014hopefully we can make them seem a bit more accessible, and bring a bit more art into the browser.\n\nGradient theory 101 (I hope that\u2019s not really a thing)\n\nRight. So before we dive into the code, let\u2019s cover a few basics. Every gradient, no matter how complex, shares a few common characteristics. Here\u2019s a straightforward one:\n\n I spent seconds hours designing this gradient. I hope you like it.\n\nAt either end of our image, we have a final color value, or color stop: on the left, our stop is white; on the right, black. And more color-rich gradients are no different:\n\n (Don\u2019t ever really do this. Please. I beg you.)\n\nIt\u2019s visually more intricate, sure. But at the heart of it, we have just seven color stops (red, orange, yellow, and so on), making for a fantastic gradient all the way.\n\nNow, color stops alone do not a gradient make. Between each is a transition point, the fail-over point between the two stops. Now, the transition point doesn\u2019t need to fall exactly between stops: it can be brought closer to one stop or the other, influencing the overall shape of the gradient.\n\nA tale of two syntaxes\n\nArmed with our new vocabulary, let\u2019s look at a CSS gradient in the wild. Behold, the simple input button:\n\n\n\nThere\u2019s a simple linear gradient applied vertically across the button, moving from a bright sunflowerish hue (#FAA51A, for you hex nuts in the audience) to a much richer orange (#F47A20). And here\u2019s the CSS that makes it happen:\n\ninput[type=submit] {\n\tbackground-color: #F47A20;\n\tbackground-image: -moz-linear-gradient(\n\t\t#FAA51A,\n\t\t#F47A20\n\t\t);\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%,\n\t\tcolor-stop(0, #FAA51A),\n\t\tcolor-stop(1, #F47A20)\n\t\t);\n}\n\nI\u2019ve borrowed David DeSandro\u2019s most excellent formatting suggestions for gradients to make this snippet a bit more legible but, still, the code above might have turned your stomach a bit. And that\u2019s perfectly understandable\u2014heck, it sort of turned mine. But let\u2019s step through the CSS slowly, and see if we can\u2019t make it a little less terrifying.\n\nVerbose WebKit is verbose\n\nHere\u2019s the syntax for our little gradient on WebKit:\n\nbackground-image: -webkit-gradient(linear, 0 0, 0 100%,\n\tcolor-stop(0, #FAA51A),\n\tcolor-stop(1, #F47A20)\n\t);\n\nWoof. Quite a mouthful, no? Well, here\u2019s what we\u2019re looking at:\n\n\n\tWebKit has a single -webkit-gradient property, which can be used to create either linear or radial gradients.\n\tThe next two values are the starting and ending positions for our gradient (0 0 and 0 100%, respectively). Linear gradients are simply drawn along the path between those two points, which allows us to change the direction of our gradient simply by altering its start and end points.\n\tAfterward, we specify our color stops with the oh-so-aptly named color-stop parameter, which takes the stop\u2019s position on the gradient (0 being the beginning, and 100% or 1 being the end) and the color itself.\n\n\nFor a simple two-color gradient like this, -webkit-gradient has a bit of shorthand notation to offer us:\n\nbackground-image: -webkit-gradient(linear, 0 0, 0 100%,\n\tfrom(#FAA51A),\n\tto(#FAA51A)\n\t);\n\nfrom(#FAA51A) is equivalent to writing color-stop(0, #FAA51A), and to(#FAA51A) is the same as color-stop(1, #FAA51A) or color-stop(100%, #FAA51A)\u2014in both cases, we\u2019re simply declaring the first and last color stops in our gradient.\n\nTerse Gecko is terse\n\nWebKit proposed its syntax back in 2008, heavily inspired by the way gradients are drawn in the canvas specification. However, a different, leaner syntax came to the fore, eventually appearing in a draft module specification in CSS3.\n\nNaturally, because nothing on the web was meant to be easy, this is the one that Mozilla has implemented.\n\nHere\u2019s how we get gradient-y in Gecko:\n\nbackground-image: -moz-linear-gradient(\n\t#FAA51A,\n\t#F47A20\n\t);\n\nWait, what? Done already? That\u2019s right. By default, -moz-linear-gradient assumes you\u2019re trying to create a vertical gradient, starting from the top of your element and moving to the bottom. And, if that\u2019s the case, then you simply need to specify your color stops, delimited with a few commas.\n\nI know: that was almost\u2026 painless. But the W3C/Mozilla syntax also affords us a fair amount of flexibility and control, by introducing features as we need them.\n\nWe can specify an origin point for our gradient:\n\nbackground-image: -moz-linear-gradient(50% 100%,\n\t#FAA51A,\n\t#F47A20\n\t);\n\nAs well as an angle, to give it a direction:\n\nbackground-image: -moz-linear-gradient(50% 100%, 45deg,\n\t#FAA51A,\n\t#F47A20\n\t);\n\nAnd we can specify multiple stops, simply by adding to our comma-delimited list:\n\nbackground-image: -moz-linear-gradient(50% 100%, 45deg,\n\t#FAA51A,\n\t#FCC,\n\t#F47A20\n\t);\n\nBy adding a percentage after a given color value, we can determine its position along the gradient path:\n\nbackground-image: -moz-linear-gradient(50% 100%, 45deg,\n\t#FAA51A,\n\t#FCC 20%,\n\t#F47A20\n\t);\n\nSo that\u2019s some of the flexibility implicit in the W3C/Mozilla-style syntax.\n\nNow, I should note that both syntaxes have their respective fans. I will say that the W3C/Mozilla-style syntax makes much more sense to me, and lines up with how I think about creating gradients. But I can totally understand why some might prefer WebKit\u2019s more verbose approach to the, well, looseness behind the -moz syntax. \u00c0 chacun son gradient syntax.\n\nStill, as the language gets refined by the W3C, I really hope some consensus is reached by the browser vendors. And with Opera signaling that it will support the W3C syntax, I suppose it falls on WebKit to do the same.\n\nReusing color stops for fun and profit\n\nBut CSS gradients aren\u2019t all simple colors and shapes and whatnot: by getting inventive with individual color stops, you can create some really complex, compelling effects.\n\nTim Van Damme, whose brain, I believe, should be posthumously donated to science, has a particularly clever application of gradients on The Box, a site dedicated to his occasional podcast series. Now, there are a fair number of gradients applied throughout the UI, but it\u2019s the feature image that really catches the eye.\n\nYou see, there\u2019s nothing that says you can\u2019t reuse color stops. And Tim\u2019s exploited that perfectly.\n\nHe\u2019s created a linear gradient, angled at forty-five degrees from the top left corner of the photo, starting with a fully transparent white (rgba(255, 255, 255, 0)). At the halfway mark, he\u2019s established another color stop at an only slightly more opaque white (rgba(255, 255, 255, 0.1)), making for that incredibly gradual brightening toward the middle of the photo.\n\n\n\nBut then he has set another color stop immediately on top of it, bringing it back down to rgba(255, 255, 255, 0) again. This creates that fantastically hard edge that diagonally bisects the photo, giving the image that subtle gloss.\n\n\n\nAnd his final color stop ends at the same fully transparent white, completing the effect. Hot? I do believe so.\n\nRocking the radials\n\nWe\u2019ve been looking at linear gradients pretty exclusively. But I\u2019d be remiss if I didn\u2019t at least mention radial gradients as a viable option, including a modest one as a link accent on a navigation bar:\n\n\n\nAnd here\u2019s the relevant CSS:\n\nbackground: -moz-radial-gradient(50% 100%, farthest-side,\n\trgb(204, 255, 255) 1%,\n\trgb(85, 85, 85) 15%,\n\trgba(85, 85, 85, 0)\n\t);\nbackground: -webkit-gradient(radial, 50% 100%, 0, 50% 100%, 15,\n\tfrom(rgb(204, 255, 255)),\n\tto(rgba(85, 85, 85, 0))\n\t);\n\nNow, the syntax builds on what we\u2019ve already learned about linear gradients, so much of it might be familiar to you, picking out color stops and transition points, as well as the two syntaxes\u2019 reliance on either a separate property (-moz-radial-gradient) or parameter (-webkit-gradient(radial, \u2026)) to shift into circular mode.\n\nMozilla introduces another stand-alone property (-moz-radial-gradient), and accepts a starting point (50% 100%) from which the circle radiates. There\u2019s also a size constant defined (farthest-side), which determines the reach and shape of our gradient.\n\nWebKit is again the more verbose of the two syntaxes, requiring both starting and ending points (50% 100% in both cases). Each also accepts a radius in pixels, allowing you to control the skew and breadth of the circle.\n\nAgain, this is a fairly modest little radial gradient. Time and article length (and, let\u2019s be honest, your author\u2019s completely inadequate grasp of geometry) prevent me from covering radial gradients in much more detail, because they are incredibly powerful. For those interested in learning more, I can\u2019t recommend the references at Mozilla and Apple strongly enough.\n\nLeave no browser behind\n\nBut no matter the kind of gradients you\u2019re working with, there is a large swathe of browsers that simply don\u2019t support gradients. Thankfully, it\u2019s fairly easy to declare a sensible fallback\u2014it just depends on the kind of fallback you\u2019d like. Essentially, gradient-blind browsers will disregard any properties containing references to either -moz-linear-gradient, -moz-radial-gradient, or -webkit-gradient, so you simply need to keep your fallback isolated from those properties.\n\nFor example: if you\u2019d like to fall back to a flat color, simply declare a separate background-color:\n\n.nav {\n\tbackground-color: #000;\n\tbackground-image: -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45));\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45)));\n}\n\nOr perhaps just create three separate background properties.\n\n.nav {\n\tbackground: #000;\n\tbackground: #000 -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45));\n\tbackground: #000 -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45)));\n}\n\nWe can even build on this to fall back to a non-gradient image:\n\n.nav {\n\tbackground: #000 url(\"faux-gradient-lol.png\") repeat-x;\n\tbackground: #000 -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45));\n\tbackground: #000 -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45)));\n}\n\nNo matter the approach you feel most appropriate to your design, it\u2019s really just a matter of keeping your fallback design quarantined from its CSS3-ified siblings.\n\n(If you\u2019re feeling especially masochistic, there\u2019s even a way to get simple linear gradients working in IE via Microsoft\u2019s proprietary filters. Of course, those come with considerable performance penalties that even Microsoft is quick to point out, so I\u2019d recommend avoiding those.\n\nAnd don\u2019t tell Andy Clarke I told you, or he\u2019ll probably unload his Derringer at me. Or something.)\n\nGo forth and, um, gradientify!\n\nIt\u2019s entirely possible your head\u2019s spinning. Heck, mine is, but that might be the effects of the \u2019nog. But maybe you\u2019re wondering why you should care about CSS gradients. After all, images are here right now, and work just fine. \n\nWell, there are some quick benefits that spring to mind: fewer HTTP requests are needed; CSS3 gradients are easily made scalable, making them ideal for variable widths and heights; and finally, they\u2019re easily modifiable by tweaking a few CSS properties. Because, let\u2019s face it, less time spent yelling at Photoshop is a very, very good thing.\n\nOf course, CSS-generated gradients are not without their drawbacks. The syntax can be confusing, and it\u2019s still under development at the W3C. As we\u2019ve seen, browser support is still very much in flux. And it\u2019s possible that gradients themselves have some real performance drawbacks\u2014so test thoroughly, and gradient carefully.\n\nBut still, as syntaxes converge, and support improves, I think generated gradients can make a compelling tool in our collective belts. The tasteful design is, of course, entirely up to you.\n\nSo have fun, and get gradientin\u2019.", "year": "2010", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2010-12-22T00:00:00+00:00", "url": "https://24ways.org/2010/everything-you-wanted-to-know-about-gradients/", "topic": "code"} {"rowid": 313, "title": "Centered Tabs with CSS", "contents": "Doug Bowman\u2019s Sliding Doors is pretty much the de facto way to build tabbed navigation with CSS, and rightfully so \u2013 it is, as they say, rockin\u2019 like Dokken. But since it relies heavily on floats for the positioning of its tabs, we\u2019re constrained to either left- or right-hand navigation. But what if we need a bit more flexibility? What if we need to place our navigation in the center?\n\nStyling the li as a floated block does give us a great deal of control over margin, padding, and other presentational styles. However, we should learn to love the inline box \u2013 with it, we can create a flexible, centered alternative to floated navigation lists.\n\nHumble Beginnings\n\nDo an extra shot of \u2018nog, because you know what\u2019s coming next. That\u2019s right, a simple unordered list:\n\n
\n \n
\n\nIf we were wedded to using floats to style our list, we could easily fix the width of our ul, and trick it out with some margin: 0 auto; love to center it accordingly. But this wouldn\u2019t net us much flexibility: if we ever changed the number of navigation items, or if the user increased her browser\u2019s font size, our design could easily break.\n\nInstead of worrying about floats, let\u2019s take the most basic approach possible: let\u2019s turn our list items into inline elements, and simply use text-align to center them within the ul:\n\n#navigation ul, #navigation ul li {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n#navigation ul {\n text-align: center;\n}\n\n#navigation ul li {\n display: inline;\n margin-right: .75em;\n}\n\n#navigation ul li.last {\n margin-right: 0;\n}\n\nOur first step is sexy, no? Well, okay, not really \u2013 but it gives us a good starting point. We\u2019ve tamed our list by removing its default styles, set the list items to display: inline, and centered the lot. Adding a background color to the links shows us exactly how the different elements are positioned.\n\nNow the fun stuff.\n\nInline Elements, Padding, and You\n\nSo how do we give our links some dimensions? Well, as the CSS specification tells us, the height property isn\u2019t an option for inline elements such as our anchors. However, what if we add some padding to them?\n\n#navigation li a {\n padding: 5px 1em;\n}\n\nI just love leading questions. Things are looking good, but something\u2019s amiss: as you can see, the padded anchors seem to be escaping their containing list.\n\nThankfully, it\u2019s easy to get things back in line. Our anchors have 5 pixels of padding on their top and bottom edges, right? Well, by applying the same vertical padding to the list, our list will finally \u201ccontain\u201d its child elements once again.\n\n\u2019Tis the Season for Tabbing\n\nNow, we\u2019re finally able to follow the \u201cSliding Doors\u201d model, and tack on some graphics:\n\n#navigation ul li a {\n background: url(\"tab-right.gif\") no-repeat 100% 0;\n color: #06C;\n padding: 5px 0;\n text-decoration: none;\n}\n\n#navigation ul li a span {\n background: url(\"tab-left.gif\") no-repeat;\n padding: 5px 1em;\n}\n\n#navigation ul li a:hover span {\n color: #69C;\n text-decoration: underline;\n}\n\nFinally, our navigation\u2019s looking appropriately sexy. By placing an equal amount of padding on the top and bottom of the ul, our tabs are properly \u201ccontained\u201d, and we can subsequently style the links within them.\n\n\n\nBut what if we want them to bleed over the bottom-most border? Easy: we can simply decrease the bottom padding on the list by one pixel, like so.\n\nA Special Note for Special Browsers\n\nThe Mac IE5 users in the audience are likely hopping up and down by now: as they\u2019ve discovered, our centered navigation behaves rather annoyingly in their browser. As Philippe Wittenbergh has reported, Mac IE5 is known to create \u201cphantom links\u201d in a block-level element when text-align is set to any value but the default value of left. Thankfully, Philippe has documented a workaround that gets that [censored] venerable browser to behave. Simply place the following code into your CSS, and the links will be restored to their appropriate width:\n\n/**//*/\n#navigation ul li a {\n display: inline-block;\n white-space: nowrap;\n width: 1px;\n}\n/**/\n\nIE for Windows, however, displays an extra kind of crazy. The padding I\u2019ve placed on my anchors is offsetting the spans that contain the left curve of my tabs; thankfully, these shenanigans are easily straightened out:\n\n/**/\n* html #navigation ul li a {\n padding: 0;\n}\n/**/\n\nAnd with that, we\u2019re finally finished.\n\nAll set.\n\nAnd that\u2019s it. With your centered navigation in hand, you can finally enjoy those holiday toddies and uncomfortable conversations with your skeevy Uncle Eustace.", "year": "2005", "author": "Ethan Marcotte", "author_slug": "ethanmarcotte", "published": "2005-12-08T00:00:00+00:00", "url": "https://24ways.org/2005/centered-tabs-with-css/", "topic": "code"}