Coding Q&A With Chris CoyierSVG Fallback, Vertical Rhythm, CSS Project Structure

Advertisement

Howdy, folks! Welcome to more Smashing Magazine CSS Q&A. It works like this: you send in questions you have about CSS, and at least once a month we’ll pick out the best questions and answer them so that everyone can benefit from the exchange. Your question could be about a very specific problem you’re having, or it could even be a question about a philosophical approach. We’ll take all kinds.

If you’re interested in exploring more Q&A, there’s a bunch more in my author archive.

CSS Project Structure

Stephen Beiler asks:

“Could you please explain your strategy for building CSS? How do you start and what does the structure of your style sheet look like? Do you use something like tip/comment helpers (e.g. the color style guide) or perhaps the related markup, or anything else? How do you structure your code?”

These days I’m using Sass for all my projects. Sass provides things that I’m sure you are all aware of — like variables and mixins, but it also provides a very simple and vital feature: includes. Just like you might use an include() function in PHP, or render a partial in Rails, you can @import another Sass file in Sass. Unlike the native CSS @import, which simply makes a request for that file, Sass goes and gets that file and includes the file’s content when compiling down to CSS.

I use this feature heavily while organizing and structuring CSS for a project. It allows me to break my styling into whatever files make sense for me, as the author. It allows me an ASCII drawing:

Ascii

On my recent redesign of CSS-Tricks, I ended up with 28 .scss files, most of which were modular bits only ever @imported into bigger style sheets. This worked really well for me, matching how I naturally organize things, and not an organization scheme forced upon me, nor one built from artificial hacks (like enormous files with commented separators).

Regarding the color style guide, one of those .scss files is always one I call _bits.scss, which is were I put all my re-usable “bits” that any of my other .scss files might need. Color variables, my own custom @mixins, etc. I’m a fan of setting up colors as variables right away in a project, so that you can reference them easily whenever needed. If you need variations on that color, you can use Sass functions like darken() and lighten() to adjust.

Slightly controversially, I like naming my colors based on their color, like $red, $blue, and $green, because then it takes me zero seconds to remember and actually use them. Whereas in the past, when I’ve tried to be super semantic about my colors and name them $brand, $secondaryHighlight, and $moduleBackground or things like that, I could never remember my own cleverness, and it slowed me down.

When To Use OOCSS

Michael Winczewski asks:

“Chris, what do you think of OOCSS? Do you use it in your code, and if so, how? When would you advise against using it? And when would you advise using it?”

I think it’s fantastic. It’s more of a way of thinking than a strict set of rules. I doubt that I understand OOCSS in the same way that Nicole Sullivan does, or that I understand SMACSS in the same way Jonathan Snook does. But I think I understand the spirit behind these movements and use them in ways that make sense to me.

What it boils down to for me is usually: write super semantic markup, but use a class name on just about every important “chunk”. Then style things largely based on those class names. It’s about identifying patterns and styling that pattern in a smart way. That way, this pattern can be re-used easily, efficiency is inherent, and no semantics are harmed. And this doesn’t mean going nuts with class names, it means using just the right amount.

Specifically to your question, I think these concepts work for every project. There isn’t anything I can think of that would warrant not doing it this way. It’s just a grown up way to approach CSS.

Selecting All Link Pseudo Classes

Ren Walker asks:

Is there a quick trick in either LESS, Sass, or with the tried and true CSS where you can select all the pseudo classes of an element? For example, instead of writing:

a, a:visited, a:active { }

You could conceivably do:

a:* { }

Sure. If you’re using Sass, you could craft your own @mixin to your needs. For instance:

@mixin all-link-psuedos($col) {
  &:link     { color: darken($col, 10%); }
  &:visisted { color: darken($col, 20%); }
  &:hover    { color: darken($col, 30%); }
  &:active   { color: darken($col, 40%); }
}

$linkColor: red;
a {
  color: $linkColor;
  @include all-link-psuedos($linkColor);
}

There is a selector combiner type of thing in just CSS as well.

:-webkit-any(a:link, a:visited, a:hover, a:active) {
  color: red;
}
:-moz-any(a:link, a:visited, a:hover, a:active) {
  color: red;
}

But this isn’t really the intended use case for it, since you could just comma separate those selectors just as easily. Plus, the browser support isn’t great. Double plus, chances are you want different styling for those things instead of the same.

Fallbacks For SVG

Angelo D’Ambrosio asks:

“What’s the simplest and most efficient way to let the browser choose whether to load the SVG or the bitmap version of an img or a CSS background, according to browser support?”

  1. Download a version of Modernizr that is trimmed down to just testing SVG (assuming that’s the only test you need).
  2. Run the test. If it passes, put in the SVG. If it fails, put in the bitmap.

Essentially:

if (!Modernizr.svg) {
  $("#logo").css("background-image", "url(fallback.png)");
}

Modernizr isn’t needed on every website in the world — it’s needed on websites where you need to very specifically fork style or behavior for browsers that do or don’t support a feature. For instance, if you have a geolocation feature on your website (but the feature works just fine by typing in an address manually), you may not need Modernizr to tell you about the lack of support, since you may not need to do anything anyway.

SVG is a perfect use case for Modernizr, because there is no simple native way to provide a fallback.

Modernizr
Modernizr gives you the clean fork you need.

Just for the record: the only reason you would need a fallback for SVG these days if you have to support IE 8 and down, or older Android.

Maintaining Vertical Rhythm

David Casey asks:

“Chris, what’s your strategy for maintaining vertical rhythm for typography / design elements in responsive design?”

Looking at a page of pure typography — where someone has set up a background of lines where you can see the vertical rhythm matching up perfectly — is pretty cool. You can get a sense for why that makes for nice reading (with the lines removed of course):

Baseline Grid

But I think it’s a bit of a fool’s errand to enforce perfection on it up and down every page of a website. One image inside the content will most likely throw the whole thing out of whack. Yeah, we could crop it, but do we want to be making choices like that for the design de jour? We could resize it, but then perhaps it’s not lining up to our vertical grid lines like we want. In a world of flexible media, I don’t think it’s worth it.

If you do think it’s worth it, do note Dan Eden’s Baseline.js which does image resizing to combat the baseline grid issue. Molten leading may also be of interest.

Does it matter if the rhythm gets off? I don’t think so. Well set text will still look good. Remember: the type will still be in rhythm with the text right around it. So who cares if it’s off with text thousands of pixels away from it, and perhaps off screen? Making sure the type looks good in general is far more important than adhering to an invisible grid dogmatically.

Responsive + Retina Background-Image

Smarajit Dasgupta asks:

“How to tackle CSS background images for both responsive and retina display. If we use a background-size of 100% to make sure the image resizes on smaller devices, how do we set the same background-size in media query (-min-device-pixel-ratio: 1.5) to half of the @2x image?

Also, to tackle images this way, should we set initial scale to one in meta viewport that we normally would for responsive websites? Would that be a problem as far as retina displays are concerned?”

This is a difficult question to answer because so much depends on the particular implementation and what your goals are. Presumably, your goals are:

  1. Make it look good all the time.
  2. Don’t waste bandwidth.

I can share with you how this works on a particular area of CSS-Tricks, in which I use a background-image that is both responsive (in that it works in a flexible width area) and retina (looks sharp on retina displays). The area is called The Lodge, and I used a snowy cabin graphic for the background.

The Lodge

That’s actually the “medium” breakpoint (I call it the “mama bear”) that many tablets see. There is a wider and narrower breakpoint as well. Like you, I want this website to look great on retina displays, but also worry about its bandwidth. Serving a background image that is big enough to look great on retina at the largest breakpoint to a non-retina display at the smallest breakpoint is not good.

What I do is put all the background-images in media queries.

/* Reverso Baby Bear */
@media (min-width: 320px) {
  .lodge-wrap {
     background: url(lodge-bg-small.jpg);
  }
}

/* Reverso Mama Bear */
@media (min-width: 800px) {
  .lodge-wrap {
     background: url(lodge-bg-medium.jpg);
  }
}

/* Reverso Papa Bear */
@media (min-width: 1400px) {
  .lodge-wrap {
     background: url(lodge-bg-large.jpg);
  }
}

Doing it this way means that only one of those will match and only one resource will be downloaded. There is also is no “default” (outside a media query) which runs the risk of starting to download before being overridden.

I also make each of those three different images larger than they need to be, and let them scale down with background-size: 100%;. That way they are retina ready all the time, whether or not the device is. A bit of a waste sometimes, but at least I’m smart enough not to supply the largest image all the time.

If you want to get extra fancy, you’d need two media queries for each breakpoint: one for retina and one for non-retina. In my case, I’d have six total media queries… they’d be pretty complex, but it’s do-able. Here’s the two for the smallest breakpoint:

@media only screen and (min-width: 320px) {

  /* Small screen, non-retina */

}

@media
only screen and (-webkit-min-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (   min--moz-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (     -o-min-device-pixel-ratio: 2/1)    and (min-width: 320px),
only screen and (        min-device-pixel-ratio: 2)      and (min-width: 320px),
only screen and (                min-resolution: 192dpi) and (min-width: 320px),
only screen and (                min-resolution: 2dppx)  and (min-width: 320px) {

  /* Small screen, retina, stuff to override above media query */

}

You’d repeat that for the next size breakpoint(s), overriding the background as you go down. Here’s more code and some more information on that.

Update: You might want to check Tim Kadlec’s media queries image analysis for background images.

Onward!

Keep up the great questions, folks! Got a good one? Send it in, and we’ll be picking the best ones for the next edition.

(vf)

↑ Back to top

I create websites and help others create better websites through writing and speaking. I consider myself a lucky man for getting to work in such a fun and rewarding field.

  1. 1

    Regarding link pseudo classes, SASS+Compass users can rely on the link-colors Compass mixin.

    0
  2. 2

    Sjors Spoorendonk

    October 15, 2012 7:22 am

    You could make a full css (apart from Modernizr) solution for .svg images with fallback. What i do is the folowing

    .logo {
    .svg .no-svg }

    In this case what happens is that the css will check for the class .svg or .no-svg wich are created by Modernizr. To me this seems a better solution since you keep everything organized in your css and you don’t need jQuery to add all these images to dom. This is the SASS way but can be done without SASS ofcourse. I like to hear your opinion :)

    0
  3. 7

    I’m confused re – the non-fancy retina images solution. Surely using min-width, a screen meeting the maximum media-query would also download all the small images as well? I.e if a screen is 1800px, it also satisfies min-width: 320px, min-width: 800px etc. Wouldn’t max-width be more appropriate?

    0
    • 8

      Agreed, but max-width wouldn’t work either with this particular implementation because anything over 1400px would get no image. It should be:

      @media (max-width: 320px) {
      .lodge-wrap {
      background: url(lodge-bg-small.jpg);
      }
      }

      @media (max-width: 800px) {
      .lodge-wrap {
      background: url(lodge-bg-medium.jpg);
      }
      }

      @media (min-width: 801px) {
      .lodge-wrap {
      background: url(lodge-bg-large.jpg);
      }
      }

      If you look at the CSS for actual The Lodge page, it looks wrong too but in a different way. A width of 800px will download both the small and medium images, i.e. satisfy both @media (min-width: 800px) and @media (max-width: 800px).

      0
      • 9

        That makes sense. I wonder If Chris has a reason for suggesting his particular solution?

        0
        • 10

          Well, it’s been a couple of days without a response. I’ve either made a silly observation or the ‘POWERS THAT BE’ like unnecessary downloads. I have next Thursay off so will test then…

          0
    • 11

      Tim Kadlec has some results regarding Media Query & Asset Downloading. Well worth the read.

      0
  4. 12

    What about this way of having SVG Fallback without the need of using javascript below:



    Edit: [ Seems the WP Comment AJAX widget strips all sorts of html and leaves the rest as invisible on its own.
    I was merely showing having an object tag defining it's an svg, have the anchor tag with the usual svg syntax, and have a IE condition to replace it with a .png in the case that it's IE 8 or less the user is using. Can't seem to delete the comment as well, it fails though it allows me to edit ]

    In case you want to have a retina version of the image can’t you merely use a css pixel ratio media query based on the specific class to switch out the fallback image for specific sizes (though I wouldn’t do that in practice).

    Does this approach also work?

    0
  5. 13

    I agree with Sjors on using the class added by Modernizr on the html tag instead of relying on javascript. Is there a specific reason why you preconise this Chris ?

    0
  6. 14
  7. 15

    Try Modernizr for SVG in Firefox 3.6 and you’ll see an epic fail.
    Also you don’t need all of these device-pixel-ratio media queries. They’re non-standard and never will be.
    So, it’s enough to use -webkit-min-device-pixel-ratio and min-resolution. See “How to unprefix -webkit-device-pixel-ratio” in CSS WG Blog: http://www.w3.org/blog/CSS/2012/06/14/unprefix-webkit-device-pixel-ratio/

    0
    • 16

      The problem is that Firefox 3.6 supports SVG, but not with IMG tags or as css backgrounds. I find if you test against “inlinesvg” using Modernizr, you’ll be able to exclude Firefox 3.6 (and less) from showing the SVG. While this isn’t the intent of “inlinesvg”, it would appear that Firefox implemented inline SVG at the same time as allow SVG use in the image tag. So it works great as a test.

      0
  8. 18

    Whenever I find this post in my newsletter, it just makes my day. You’re doing a supa awesome job serving the web design community, Chris. Thank you!

    0
  9. 19

    Chris, why do you prefer better using Modernizer over HTML image object ‘onerror’ event for preparing fallback for SVG graphics? Have a look:

    <img src="image.svg" onerror="this.removeAttribute('onerror'); this.src='image.png';" />

    With this approach it’s not needed to query images from the DOM three every time you render them. Imagine if you render some HTML dynamically with templates mechanism or just as AJAX call output…
    Arguments against/for?

    0
    • 20

      Never heard of that but it seems pretty smart.

      0
    • 21

      I think the drawback is that the browser must download the SVG, fail rendering it, and proceed with fallback. Not so a perfomant way.

      I think the ideal way will be detect browser server-side: set a class like “svg” or “nosvg” on body, and then correct it with Javascript if it’s turned on.

      0
  10. 22

    What bothers my about using SCSS is that it isn’t used by PHP and you need to use a pre-compiler to get it working on your site. Since older browsers aren’t really compatible with those fancy css tags, it is likely to break. Not a big deal if you are aiming for fresh devices on servers where you can install scss compilers and whatnot, but that isn’t always the deal.

    SCSS seems like a great language and when it is nativly supported by apache or whatnot, i would switch, but at the moment it seems like a big hassle to get this stuff working. Both in development as in release.

    You could use a framework that supports this, but i don’t always do and most popular CMS systems don’t support it (yet)

    0
    • 23

      Dude, nobody makes the server do the work. Though, it is possible (there is a php LESS processor for example), it’s not smart nor efficient. I write some styles in LESS in my normal text editor, and as soon as I hit save, it spits out CSS. Not only is this not a “hassle” to use, but it makes writing styles much easier to organize. Just upload the CSS. The server never sees the SCSS.

      0
  11. 24

    > Fallbacks For SVG
    > if (!Modernizr.svg) {

    Wrong.

    Firefox 3.6 supports SVG according to Modernizr (as img element), but it doesn’t support SVG in background images. Only Firefox 4.0 supports it, so it should be .inlinesvg as FF 4.0+ supports both inline SVG and SVG in background images.

    0
  12. 25

    Michiel Verkoijen

    October 22, 2012 5:56 am

    Hi Greli and Vadim, I published an article last week because we had a similar problem with detecting SVG support for the IMG element and background CSS images. Most of the other techniques out there are not compatible with Firefox 3.6. http://voormedia.com/blog/2012/10/displaying-and-detecting-support-for-svg-images

    0
  13. 26

    Great post! It’s definitely really helpful to those who have some questions about how to design responsively. We also had a question from one of our readers on an issue she’s having with her responsive website. http://www.responsivewebdesignblog.com/2012/09/responsive-web-design-questions-that-need-answering/

    0
  14. 27

    Cool article, Chris. It’s an awesome technique for Retina-ready background. Thank you!

    0
  15. 28

    Can you make it so that Compass compiles only the global.css file instead of creating a css file for each and every one of the scss files?

    0
    • 29

      Sure, you just have to prefix with “_” all the scss file you don’t want to be created as css.

      “foo.scss” will be created as “foo.css”, but “_foo.scss” will be ignored from Compass. The prefix “_” has other features, this is in the scss reference.

      0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top