24ways

Custom SQL query returning 4 rows (hide)

Query parameters

rowidtitlecontentsyearauthorauthor_slugpublishedurltopic
54 Putting My Patterns through Their Paces 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. The 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. Meet the Teaser Here’s 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.) In its simplest form, a teaser contains a headline, which links to an article: Fairly straightforward, sure. But it’s 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 – 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. Nearly every element visible on this page is built out of our generic “teaser” pattern. But the teaser variation I’d like to call out is the one that appears on The Toast’s 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. The approved visual design of our teaser, as it appears on lists on the homepage and the section fronts. And this is, as it happens, the teaser variation that gave me pause. Back in the old days – you know, like six months ago – I probably would’ve marked this module up to match the design. In other words, I would’ve looked at the module’s visual hierarchy (metadata up top, headline and content below) and written the following HTML: <div class="teaser"> <p class="article-byline">By <a href="#">Author Name</a></p> <a class="comment-count" href="#">126 <i>comments</i></a> <h1 class="article-title"><a href="#">Article Title</a></h1> <p class="teaser-excerpt">Lorem ipsum dolor sit amet, consectetur…</p> </div> But then I caught myself, and realized this wasn’t the best approach. Moving Beyond Layout Since I’ve started working responsively, there’s a question I work into every step of my design process. Whether I’m working in Sketch, CSSing a thing, or researching a project, I try to constantly ask myself: What if someone doesn’t browse the web like I do? …Okay, that doesn’t seem especially fancy. (And maybe you came here for fancy.) But as straightforward as that question might seem, it’s been invaluable to so many aspects of my practice. If I’m working on a widescreen layout, that question helps me remember the constraints of the small screen; if I’m working on an interface that has some enhancements for touch, it helps me consider other input modes as I work. It’s 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. And 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’d 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’re associated. That’s why I find it’s helpful to begin designing a pattern’s hierarchy before its layout: to move past the visual presentation in front of me, and focus on the underlying content I’m trying to support. In other words, if someone’s encountering my design without the CSS I’ve written, what should their experience be? So I took a step back, and came up with a different approach: <div class="teaser"> <h1 class="article-title"><a href="#">Article Title</a></h1> <h2 class="article-byline">By <a href="#">Author Name</a></h2> <p class="teaser-excerpt"> Lorem ipsum dolor sit amet, consectetur… <a class="comment-count" href="#">126 <i>comments</i></a> </p> </div> Much, much better. This felt like a better match for the content I was designing: the headline – easily most important element – was at the top, followed by the author’s 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’s why it’s at the very end of the excerpt, the last element within our teaser. And with some light styling, we’ve got a respectable-looking hierarchy in place: Yeah, you’re right – it’s not our final design. But from this basic-looking foundation, we can layer on a bit more complexity. First, we’ll bolster the markup with an extra element around our title and byline: <div class="teaser"> <div class="teaser-hed"> <h1 class="article-title"><a href="#">Article Title</a></h1> <h2 class="article-byline">By <a href="#">Author Name</a></h2> </div> … </div> With that in place, we can use flexbox to tweak our layout, like so: .teaser-hed { display: flex; flex-direction: column-reverse; } flex-direction: column-reverse acts a bit like a change in gravity within our teaser-hed element, vertically swapping its two children. Getting closer! But as great as flexbox is, it doesn’t do anything for elements outside our container, like our little comment count, which is, as you’ve probably noticed, still stranded at the very bottom of our teaser. Flexbox 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’s using a sufficiently modern version of flexbox. Here’s the one we used: var doc = document.body || document.documentElement; var style = doc.style; if ( style.webkitFlexWrap == '' || style.msFlexWrap == '' || style.flexWrap == '' ) { doc.className += " supports-flex"; } Eagle-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’s design: .supports-flex .teaser-hed { display: flex; flex-direction: column-reverse; } .supports-flex .teaser .comment-count { position: absolute; right: 0; top: 1.1em; } If the supports-flex class is present, we can apply our flexbox layout to the title area, sure – 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’t meet our threshold for our advanced styles are left with an attractive design that matches our HTML’s content hierarchy; but the ones that pass our test receive the finished, final design. And with that, our teaser’s complete. Diving Into Device-Agnostic Design This is, admittedly, a pretty modest application of flexbox. (For some truly next-level work, I’d recommend Heydon Pickering’s “Flexbox Grid Finesse”, 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’d be right! In fact, it’s 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’ve found that thinking about my design as existing in broad experience tiers – in layers – is one of the best ways of designing for the modern web. And what’s more, it works not just for simple modules like our teaser, but for more complex or interactive patterns as well. Open video Even a simple search form can be conditionally enhanced, given a little layered thinking. This more layered approach to interface design isn’t a new one, mind you: it’s 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’ve found to practice responsive design. As Trent Walton once wrote, Like cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web’s inherent variability. We have a weird job, working on the web. We’re designing for the latest mobile devices, sure, but we’re increasingly aware that our definition of “smartphone” is much too narrow. Browsers have started appearing on our wrists and in our cars’ dashboards, but much of the world’s mobile data flows over sub-3G networks. After all, the web’s evolution has never been charted along a straight line: it’s 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’t yet know about, a more device-agnostic, more layered design process can better prepare our patterns – and ourselves – for the future. (It won’t help you get enough to eat at holiday parties, though.) 2015 Ethan Marcotte ethanmarcotte 2015-12-10T00:00:00+00:00 https://24ways.org/2015/putting-my-patterns-through-their-paces/ code
162 Conditional Love “Browser.” The four-letter word of web design. I mean, let’s face it: on the good days, when things just work in your target browsers, it’s marvelous. The air smells sweeter, birds’ songs sound more melodious, and both your design and your code are looking sharp. But on the less-than-good days (which is, frankly, most of them), you’re 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. Thankfully, we do have an out for those little inconsistencies that crop up when dealing with cross-browser testing: CSS patches. Spare the Rod, Hack the Browser Before committing browsercide over some rendering bug, a designer will typically reach for a snippet of CSS fix the faulty browser. Historically referred to as “hacks,” I prefer Dan Cederholm’s more client-friendly alternative, “patches”. But 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. Traditionally, this has been done either by exploiting incomplete CSS support: #content { height: 1%; // Let's force hasLayout for old versions of IE. line-height: 1.6; padding: 1em; } html>body #content { height: auto; // Modern browsers get a proper height value. } or by exploiting bugs in their rendering engine to deliver alternate style rules: #content p { font-size: .8em; /* Hide from Mac IE5 \*/ font-size: .9em; /* End hiding from Mac IE5 */ } We’ve even used these exploits to serve up whole stylesheets altogether: @import url("core.css"); @media tty { i{content:"\";/*" "*/}} @import 'windows-ie5.css'; /*";} }/* */ The list goes on, and on, and on. For every browser, for every bug, there’s a patch available to fix some rendering bug. But after some time working with standards-based layouts, I’ve found that CSS patches, as we’ve traditionally used them, become increasingly difficult to maintain. As stylesheets are modified over the course of a site’s lifetime, inline fixes we’ve 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. Giving the Kids Separate Rooms Since I joined Airbag Industries earlier this year, every project we’ve worked on has this in the head of its templates: <link rel="stylesheet" href="-/css/screen/main.css" type="text/css" media="screen, projection" /> <!--[if lt IE 7]> <link rel="stylesheet" href="-/css/screen/patches/win-ie-old.css" type="text/css" media="screen, projection" /> <![endif]--> <!--[if gte IE 7]> <link rel="stylesheet" href="-/css/screen/patches/win-ie7-up.css" type="text/css" media="screen, projection" /> <![endif]--> The first element is, simply enough, a link element that points to the project’s 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. But don’t reach for the mulled wine quite yet. Immediately after, we’ve 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’ve got one for IE 6 and below: <!--[if lt IE 7]> <link rel="stylesheet" href="-/css/screen/patches/win-ie-old.css" type="text/css" media="screen, projection" /> <![endif]--> And another for IE7 and above: <!--[if gte IE 7]> <link rel="stylesheet" href="-/css/screen/patches/win-ie7-up.css" type="text/css" media="screen, projection" /> <![endif]--> Microsoft’s conditional comments aren’t exactly new, but they can be a valuable alternative to cooking CSS patches directly into a master stylesheet. And though they’re not a W3C-approved markup structure, I think they’re just brilliant because they innovate within the spec: non-IE devices will assume that the comments are just that, and ignore the markup altogether. This does, of course, mean that there’s 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’t need them. Namely, we no longer have to write rules like this in our main stylesheet: #content { height: 1%; // Let's force hasLayout for old versions of IE. line-height: 1.6; padding: 1em; } html>body #content { height: auto; // Modern browsers get a proper height value. } Rather, we can simply write an un-patched rule in our core stylesheet: #content { line-height: 1.6; padding: 1em; } And now, our patch for older versions of IE goes in—you guessed it—the stylesheet for older versions of IE: #content { height: 1%; } The hasLayout patch is applied, our design’s repaired, and—most importantly—the patch is only seen by the browser that needs it. The “good” browsers don’t have to incur any added stylesheet weight from our IE patches, and Internet Explorer gets the conditional love it deserves. Most importantly, this “compartmentalized” 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’t 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. Even Good Children Misbehave While IE may occupy the bulk of our debugging time, there’s 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 “good browsers” back in line with our design? Assuming you’re loving the “one patch file per browser” model as much as I do, there’s just one alternative: JavaScript. function isSaf() { var isSaf = (document.childNodes && !document.all && !navigator.taintEnabled && !navigator.accentColorName) ? true : false; return isSaf; } function isOp() { var isOp = (window.opera) ? true : false; return isOp; } Instead of relying on dotcom-era tactics of parsing the browser’s user-agent string, we’re testing here for support for various DOM objects, whose presence or absence we can use to reasonably infer the browser we’re looking at. So running the isOp() function, for example, will test for Opera’s proprietary window.opera object, and thereby accurately tell you if your user’s running Norway’s finest browser. With scripts such as isOp() and isSaf() in place, you can then reasonably test which browser’s viewing your content, and insert additional link elements as needed. function loadPatches(dir) { if (document.getElementsByTagName() && document.createElement()) { var head = document.getElementsByTagName("head")[0]; if (head) { var css = new Array(); if (isSaf()) { css.push("saf.css"); } else if (isOp()) { css.push("opera.css"); } if (css.length) { var link = document.createElement("link"); link.setAttribute("rel", "stylesheet"); link.setAttribute("type", "text/css"); link.setAttribute("media", "screen, projection"); for (var i = 0; i < css.length; i++) { var tag = link.cloneNode(true); tag.setAttribute("href", dir + css[0]); head.appendChild(tag); } } } } } Here, we’re 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. Fire it up using your favorite onload or DOMContentLoaded function, and you’re good to go. Scripteat Emptor At this point, some of the audience’s more conscientious ‘scripters may be preparing to lob figgy pudding at this author’s head. And that’s perfectly understandable; relying on JavaScript to patch CSS chafes a bit against the normally clean separation we have between our pages’ content, presentation, and behavior layers. And beyond the philosophical concerns, this approach comes with a few technical caveats attached: Browser detection? So un-133t. Browser detection is not something I’d 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. It’s JavaScript, so don’t count on it being available. According to one site, roughly four percent of Internet users don’t have JavaScript enabled. Your site’s stats might be higher or lower than this number, but still: don’t expect that every member of your audience will see these additional stylesheets, and ensure that your content’s still accessible with JS turned off. Be a constant gardener. The sample isSaf() and isOp() functions I’ve written will tell you if the user’s 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. You 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’t become a bug tomorrow. Patching Firefox, Opera, and Safari isn’t something I’ve had to do frequently: still, there have been occasions where the above script’s come in handy. Between conditional comments, careful CSS auditing, and some judicious JavaScript, browser-based bugs can be handled with near-surgical precision. So pass the ‘nog. It’s patchin’ time. 2007 Ethan Marcotte ethanmarcotte 2007-12-15T00:00:00+00:00 https://24ways.org/2007/conditional-love/ code
238 Everything You Wanted To Know About Gradients (And a Few Things You Didn’t) Hello. I am here to discuss CSS3 gradients. Because, let’s face it, what the web really needed was more gradients. Still, despite their widespread use (or is it overuse?), the smartly applied gradient can be a valuable contributor to a designer’s vocabulary. There’s 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. Of course, that whole ‘proper application’ thing is the tricky bit. But given their place in our toolkit and their prominence online, it really is heartening to see we can create gradients directly with CSS. They’re part of the draft images module, and implemented in two of the major rendering engines. Still, I’ve always found CSS gradients to be one of the more confusing aspects of CSS3. So if you’ll indulge me, let’s take a quick look at how to create CSS gradients—hopefully we can make them seem a bit more accessible, and bring a bit more art into the browser. Gradient theory 101 (I hope that’s not really a thing) Right. So before we dive into the code, let’s cover a few basics. Every gradient, no matter how complex, shares a few common characteristics. Here’s a straightforward one: I spent seconds hours designing this gradient. I hope you like it. At 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: (Don’t ever really do this. Please. I beg you.) It’s 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. Now, 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’t need to fall exactly between stops: it can be brought closer to one stop or the other, influencing the overall shape of the gradient. A tale of two syntaxes Armed with our new vocabulary, let’s look at a CSS gradient in the wild. Behold, the simple input button: There’s 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’s the CSS that makes it happen: input[type=submit] { background-color: #F47A20; background-image: -moz-linear-gradient( #FAA51A, #F47A20 ); background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(0, #FAA51A), color-stop(1, #F47A20) ); } I’ve borrowed David DeSandro’s 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’s perfectly understandable—heck, it sort of turned mine. But let’s step through the CSS slowly, and see if we can’t make it a little less terrifying. Verbose WebKit is verbose Here’s the syntax for our little gradient on WebKit: background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(0, #FAA51A), color-stop(1, #F47A20) ); Woof. Quite a mouthful, no? Well, here’s what we’re looking at: WebKit has a single -webkit-gradient property, which can be used to create either linear or radial gradients. The 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. Afterward, we specify our color stops with the oh-so-aptly named color-stop parameter, which takes the stop’s position on the gradient (0 being the beginning, and 100% or 1 being the end) and the color itself. For a simple two-color gradient like this, -webkit-gradient has a bit of shorthand notation to offer us: background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#FAA51A), to(#FAA51A) ); from(#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)—in both cases, we’re simply declaring the first and last color stops in our gradient. Terse Gecko is terse WebKit 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. Naturally, because nothing on the web was meant to be easy, this is the one that Mozilla has implemented. Here’s how we get gradient-y in Gecko: background-image: -moz-linear-gradient( #FAA51A, #F47A20 ); Wait, what? Done already? That’s right. By default, -moz-linear-gradient assumes you’re trying to create a vertical gradient, starting from the top of your element and moving to the bottom. And, if that’s the case, then you simply need to specify your color stops, delimited with a few commas. I know: that was almost… painless. But the W3C/Mozilla syntax also affords us a fair amount of flexibility and control, by introducing features as we need them. We can specify an origin point for our gradient: background-image: -moz-linear-gradient(50% 100%, #FAA51A, #F47A20 ); As well as an angle, to give it a direction: background-image: -moz-linear-gradient(50% 100%, 45deg, #FAA51A, #F47A20 ); And we can specify multiple stops, simply by adding to our comma-delimited list: background-image: -moz-linear-gradient(50% 100%, 45deg, #FAA51A, #FCC, #F47A20 ); By adding a percentage after a given color value, we can determine its position along the gradient path: background-image: -moz-linear-gradient(50% 100%, 45deg, #FAA51A, #FCC 20%, #F47A20 ); So that’s some of the flexibility implicit in the W3C/Mozilla-style syntax. Now, 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’s more verbose approach to the, well, looseness behind the -moz syntax. À chacun son gradient syntax. Still, 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. Reusing color stops for fun and profit But CSS gradients aren’t all simple colors and shapes and whatnot: by getting inventive with individual color stops, you can create some really complex, compelling effects. Tim 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’s the feature image that really catches the eye. You see, there’s nothing that says you can’t reuse color stops. And Tim’s exploited that perfectly. He’s 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’s 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. But 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. And his final color stop ends at the same fully transparent white, completing the effect. Hot? I do believe so. Rocking the radials We’ve been looking at linear gradients pretty exclusively. But I’d be remiss if I didn’t at least mention radial gradients as a viable option, including a modest one as a link accent on a navigation bar: And here’s the relevant CSS: background: -moz-radial-gradient(50% 100%, farthest-side, rgb(204, 255, 255) 1%, rgb(85, 85, 85) 15%, rgba(85, 85, 85, 0) ); background: -webkit-gradient(radial, 50% 100%, 0, 50% 100%, 15, from(rgb(204, 255, 255)), to(rgba(85, 85, 85, 0)) ); Now, the syntax builds on what we’ve 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’ reliance on either a separate property (-moz-radial-gradient) or parameter (-webkit-gradient(radial, …)) to shift into circular mode. Mozilla introduces another stand-alone property (-moz-radial-gradient), and accepts a starting point (50% 100%) from which the circle radiates. There’s also a size constant defined (farthest-side), which determines the reach and shape of our gradient. WebKit 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. Again, this is a fairly modest little radial gradient. Time and article length (and, let’s be honest, your author’s 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’t recommend the references at Mozilla and Apple strongly enough. Leave no browser behind But no matter the kind of gradients you’re working with, there is a large swathe of browsers that simply don’t support gradients. Thankfully, it’s fairly easy to declare a sensible fallback—it just depends on the kind of fallback you’d 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. For example: if you’d like to fall back to a flat color, simply declare a separate background-color: .nav { background-color: #000; background-image: -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45)); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45))); } Or perhaps just create three separate background properties. .nav { background: #000; background: #000 -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45)); background: #000 -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45))); } We can even build on this to fall back to a non-gradient image: .nav { background: #000 <strong>url("faux-gradient-lol.png") repeat-x</strong>; background: #000 -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45)); background: #000 -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0)), to(rgba(255, 255, 255, 0.45))); } No matter the approach you feel most appropriate to your design, it’s really just a matter of keeping your fallback design quarantined from its CSS3-ified siblings. (If you’re feeling especially masochistic, there’s even a way to get simple linear gradients working in IE via Microsoft’s proprietary filters. Of course, those come with considerable performance penalties that even Microsoft is quick to point out, so I’d recommend avoiding those. And don’t tell Andy Clarke I told you, or he’ll probably unload his Derringer at me. Or something.) Go forth and, um, gradientify! It’s entirely possible your head’s spinning. Heck, mine is, but that might be the effects of the ’nog. But maybe you’re wondering why you should care about CSS gradients. After all, images are here right now, and work just fine. Well, 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’re easily modifiable by tweaking a few CSS properties. Because, let’s face it, less time spent yelling at Photoshop is a very, very good thing. Of course, CSS-generated gradients are not without their drawbacks. The syntax can be confusing, and it’s still under development at the W3C. As we’ve seen, browser support is still very much in flux. And it’s possible that gradients themselves have some real performance drawbacks—so test thoroughly, and gradient carefully. But 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. So have fun, and get gradientin’. 2010 Ethan Marcotte ethanmarcotte 2010-12-22T00:00:00+00:00 https://24ways.org/2010/everything-you-wanted-to-know-about-gradients/ code
313 Centered Tabs with CSS Doug Bowman’s Sliding Doors is pretty much the de facto way to build tabbed navigation with CSS, and rightfully so – it is, as they say, rockin’ like Dokken. But since it relies heavily on floats for the positioning of its tabs, we’re 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? Styling 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 – with it, we can create a flexible, centered alternative to floated navigation lists. Humble Beginnings Do an extra shot of ‘nog, because you know what’s coming next. That’s right, a simple unordered list: <div id="navigation"> <ul> <li><a href="#"><span>Home</span></a></li> <li><a href="#"><span>About</span></a></li> <li><a href="#"><span>Our Work</span></a></li> <li><a href="#"><span>Products</span></a></li> <li class="last"><a href="#"><span>Contact Us</span></a></li> </ul> </div> If 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’t net us much flexibility: if we ever changed the number of navigation items, or if the user increased her browser’s font size, our design could easily break. Instead of worrying about floats, let’s take the most basic approach possible: let’s turn our list items into inline elements, and simply use text-align to center them within the ul: #navigation ul, #navigation ul li { list-style: none; margin: 0; padding: 0; } #navigation ul { text-align: center; } #navigation ul li { display: inline; margin-right: .75em; } #navigation ul li.last { margin-right: 0; } Our first step is sexy, no? Well, okay, not really – but it gives us a good starting point. We’ve 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. Now the fun stuff. Inline Elements, Padding, and You So how do we give our links some dimensions? Well, as the CSS specification tells us, the height property isn’t an option for inline elements such as our anchors. However, what if we add some padding to them? #navigation li a { padding: 5px 1em; } I just love leading questions. Things are looking good, but something’s amiss: as you can see, the padded anchors seem to be escaping their containing list. Thankfully, it’s 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 “contain” its child elements once again. ’Tis the Season for Tabbing Now, we’re finally able to follow the “Sliding Doors” model, and tack on some graphics: #navigation ul li a { background: url("tab-right.gif") no-repeat 100% 0; color: #06C; padding: 5px 0; text-decoration: none; } #navigation ul li a span { background: url("tab-left.gif") no-repeat; padding: 5px 1em; } #navigation ul li a:hover span { color: #69C; text-decoration: underline; } Finally, our navigation’s looking appropriately sexy. By placing an equal amount of padding on the top and bottom of the ul, our tabs are properly “contained”, and we can subsequently style the links within them. But 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. A Special Note for Special Browsers The Mac IE5 users in the audience are likely hopping up and down by now: as they’ve discovered, our centered navigation behaves rather annoyingly in their browser. As Philippe Wittenbergh has reported, Mac IE5 is known to create “phantom links” 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: /**//*/ #navigation ul li a { display: inline-block; white-space: nowrap; width: 1px; } /**/ IE for Windows, however, displays an extra kind of crazy. The padding I’ve placed on my anchors is offsetting the spans that contain the left curve of my tabs; thankfully, these shenanigans are easily straightened out: /**/ * html #navigation ul li a { padding: 0; } /**/ And with that, we’re finally finished. All set. And that’s it. With your centered navigation in hand, you can finally enjoy those holiday toddies and uncomfortable conversations with your skeevy Uncle Eustace. 2005 Ethan Marcotte ethanmarcotte 2005-12-08T00:00:00+00:00 https://24ways.org/2005/centered-tabs-with-css/ code