Coding Q&A With Chris Coyier: Box-Sizing and CSS Sprites

Advertisement

Howdy, folks! Welcome to the new incarnation of Smashing Magazine’s Q&A. It’s going to work like this: you send in questions you have about CSS1, 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 are having, or it could be a question about philosophical approach. We’ll take all kinds.

We’ve done a bit of this before with a wider scope, so if you enjoy reading the Q&A, check out my author archive2 for more of them.

Box Sizing

Question from Brad Frost:

What are your thoughts on Paul Irish’s idea3 to apply box-sizing: border-box to every element on the page?

Using box-sizing is super-helpful, especially for mobile and responsive design (for example, getting fully fluid form fields with fixed amounts of padding is awesome). But I’m leery of applying it to everything.

Besides browser support (I’ve already run into issues with some less-than-smart mobile browsers), can you think of any downsides to this technique?

An armchair critic of this technique would whine about the performance of the universal selector (*). This whine has been largely debunked. While this selector technically is “slower” than something like a class name selector, the difference is negligible, except in extreme cases of overuse or on pages with zillions of elements. Doing something that reduces one HTTP request makes at least an order of magnitude bigger difference than optimizing selectors.

For the record, the complete and recommended syntax is this:

* {
   -webkit-box-sizing: border-box;
   -moz-box-sizing:    border-box;
   box-sizing:         border-box;
}

With this, you essentially get perfect browser support in everything — even the vast majority of mobile Webkits. The notable exception is IE 7 and below. I don’t want to open a can of worms, but IE 7 usage is already low and dropping much faster than IE 6 did, so supporting only IE 8+ will be commonplace very soon.

Here’s a quick primer on why using this box model is nice:

  • Now, when you set a width and height, the element will always be that width and height, regardless of padding and borders.
  • This makes math a lot easier. For example, you could easily make a four-column grid by making the width of each column 25% and floating them. You could make gutters out of pixel padding and not worry that they will expand the columns and break the grid.
  • It’s also extra useful for text areas that you want to fill to their parent’s width, which you can only do by setting their width to 100%. But then you wouldn’t be able to have padding unless you used this box model, lest they expand beyond the parent’s width.

You mention a problem with a mobile browser but not exactly what the problem is or which mobile browser. It would be interesting to know which browser and what the problem is, so if you could follow up in the comments, that would be great.

For me, I’m using it on everything I build from here on out. It’s been fantastic so far, and I see no reason not to go with this empirically better box model.

CSS Sprites Workflow

Question from Matt Banks:

What’s your preferred method for creating and managing CSS sprites? Do you use Photoshop to manually create your own sprites, a Web service or an app like SpriteRight4? For updating sprites with new images, what workflow is best and easiest?

I have an article from 20105 about my workflow for CSS sprites, in which step 1 is this:

Ignore sprites entirely. Make every background image its own separate image and reference them as such in the CSS.

Of course, I’m not suggesting that you don’t use sprites. Quite the contrary: I think using sprites and having a good workflow are paramount to being a good front-end coder and often the number one thing you can do to optimize Web performance. What I was trying to say is don’t pre-optimize. Pre-optimization is quicksand for developers: you spend a lot of time flailing your arms but not getting anywhere. You know that sprites are good, and so you start building with them right away, spending all kinds of time tweaking and adjusting and calculating the sprites to be just right during development.


(Image: electricnerve6)

This is a waste of time. Instead, ignore sprites on new projects until you have reached a comfortable level of maturity with your CSS or are just about to go live. Then, take the time to go through and get yourself all sprited up. It will be easier and quicker.

In terms of workflow, I’m still a fan of SpriteMe7, which is a bookmarklet that finds images in use on your page and suggests or creates a sprite for you and even helps you with the CSS. SpriteMe only works on one page at a time, though, which might not be good enough for complex apps. I’m also a big fan of SpriteCow8, in which you handcraft your own sprite (in Photoshop or some other image-editing program), and then it helps you identify the parts with a really great UI and gives you the CSS needed to use a particular image inside the sprite. I think the SpriteCow workflow is a bit better because you are working from a sprite that you made yourself by looking through your images directory, so it’s more comprehensive and to your own style.

To take things to the next level with your CSS sprites workflow, you should really check out how Compass9 handles it10. RailsCasts has a screencast11 that teaches you about it. It’s pretty awesome. You just use individual images as normal (remember, with no pre-optimization) and drop them into an images directory. Compass will see the new image and automatically add it to a master sprite image. It creates a class name for the new image, with all of the correct sizing and positioning. Then, anywhere you want to use this new image as a sprite, either use that class in your HTML or @extend that class in your CSS. Efficient, easy and super-fancy.

Triangles

Question from Jakob Cosoroaba:

All boxes are square to the browser. What’s the best way to fake a triangle box?

To set the stage here, you can “fake” a triangle in a number of ways. The most common is by exploiting the fact that borders end at an angle when they touch each other at corners. So, by collapsing a box to a width and height of 0 and setting the color for only one border, we can make a triangle. A lot of examples of this are on Shapes of CSS12. We could draw a triangle with SVG or canvas. We could even make a triangle, with linear-gradient as the background of an element, as easily as this: background: linear-gradient(45deg, white 90%, blue 90%); (with all of the vendor prefixes, of course).

But none of these techniques will help us here. In his original question, Jakob Cosoroaba lists two techniques that he has tried. One13 involves rotate transformations and the clip property; the problem being that IE 9 has too large of a rollover area14 (i.e. it’s not limited to the triangle). The second technique15 uses slightly less markup, using only rotate transformations; the problem here being that you cannot add content inside. This made clear what he needs:

  1. The ability to put content inside;
  2. The ability to make the triangle (and only the triangle) a link.

Jakob, you should have taken your already clever work just a step further! By combining your two techniques, you could make the link the correct size (even in IE) and put content inside. Just make the link sit on top with z-index.

Here’s a demo of the combined techniques16.

Yep, doing this with markup feels a bit hacky. This is just one of those things that CSS isn’t great at right now.

Server-Side Optimization

Question from Patrick Schreiner:

I was wondering if you could provide some insight into what one should keep in mind for server-side optimization and performance when it comes to CSS? Are there any red flags to look out for? What’s your approach to making sure that code performs well and that it’s optimized for heavy server-side optimization?

I’m not a great server-side guy, but I can list some tips that might be helpful. Perhaps some server folks can help out in the comments.

  • Just serve CSS straight up.
    … Not PHP that has to be run and that then serves as a CSS content type, and not LESS that needs to be interpreted client side — just plain old CSS.
  • Serve it compressed.
    There is no reason for CSS to be optimized for human readability. Strip out all non-relevant white space and comments.
  • Gzip it.
    If you’re running an Apache server (fairly likely), you could put an .htaccess file at the root of your website that tells the server to serve your CSS Gzip’ed. Check out the code starting at line 162 in HTML5 Boilerplate’s .htaccess1817 file for how to do that.
  • Cache it.
    The fastest file is one you don’t have to serve at all. So, when you do serve a CSS file, tell the browser to keep it around for a long time (a year is a good rule of thumb). Then, if you change the CSS, you can break the cache by changing the file’s name (for example, global.v23453.css). Check out the code starting at line 267 in HTML5 Boilerplate’s .htaccess1817 file for how to do that.
  • Keep it small.
    If your CSS file is 2 MB, you’re doing it wrong. Maybe you need to get a bit more OOCSS19 in your approach, doing things more modularly with very reusable bits of style.
  • One, two or three
    That’s how many CSS files should be loaded on any given page. One if the website is one page. Two for websites of medium complexity, using a global CSS file that all pages need and a second file for subsections of the website that are different enough to warrant one. Three for fairly complex websites that need global, section-specific and page-specific styles.

Onward!

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

(al)

Footnotes

  1. 1 https://smashingcoding.wufoo.com/forms/ask-chris-coyier-your-css-question/
  2. 2 http://www.smashingmagazine.com/author/chris-coyier/
  3. 3 http://paulirish.com/2012/box-sizing-border-box-ftw/
  4. 4 http://spriterightapp.com/
  5. 5 http://css-tricks.com/css-sprites-workflow/
  6. 6 http://www.flickr.com/photos/electricnerve/2666030594/sizes/z/in/photostream/
  7. 7 http://spriteme.org/
  8. 8 http://www.spritecow.com/
  9. 9 http://compass-style.org/
  10. 10 http://compass-style.org/help/tutorials/spriting/
  11. 11 http://railscasts.com/episodes/334-compass-css-sprites
  12. 12 http://css-tricks.com/examples/ShapesOfCSS/
  13. 13 http://jsfiddle.net/cosoroaba/nCEwv/
  14. 14 http://www.screenr.com/ikos
  15. 15 http://jsfiddle.net/exKJK/
  16. 16 http://jsfiddle.net/chriscoyier/xtCb9/1/
  17. 17 https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess
  18. 18 https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess
  19. 19 https://github.com/stubbornella/oocss/
  20. 20 https://smashingcoding.wufoo.com/forms/ask-chris-coyier-your-css-question/
CSS

↑ Back to topShare on Twitter

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.

Advertising
  1. 1

    For server-side optimization, using a CDN like Rackspace Cloud Files or Amazon Cloud Front is helpful for optimizing bandwidth and latency around the world. It also takes load off your servers and minimizes HTTP request overhead (cookies aren’t sent since the request is off your domain). Check gzipwtf.com to make sure your assets are bein served with gzip.

    1
  2. 2

    I’d rather add box-sizing where needed than everywhere (my reasoning? Cause got used to it).

    1
  3. 3

    Oh… so we all like the old IE box model instead?! Wow! Who’d-a-thunk that?! I always liked that model. If I have a phyical box… I consider the entire width as the physical width of the container (no matter how much padding I put around the content). Padding and content should always be contained within the set width and not expand it.

    0
    • 4

      Francis Thibault

      June 18, 2012 6:03 am

      When I started learning CSS I always thought that the box model was including padding and margins (IE way), and to me it made sense! Especially as a former graphic designer.

      1
  4. 5

    J Cole Morrison

    June 14, 2012 9:24 am

    Awesome. I love CSS-Tricks. It’s one of the best websites on the freaking web – and this article just further proves that. Thanks for the tips Chris Coyier!

    0
  5. 6

    Francis Villanueva

    June 14, 2012 9:28 am

    With frameworks like Compass/Sass and Less, I believe EVERYONE should be doing sprite sheets since it’s all automated and done for you. That whole tedious process is eliminated and done on the fly as you work.

    I believe these frameworks as they’re the most efficient tools for CSS development today and are worth a mention in your article.

    http://compass-style.org/
    http://compass-style.org/reference/compass/helpers/sprites/

    0
    • 7

      Nathaniel Higgins

      June 16, 2012 3:42 pm

      You need to keep in mind the variety of situations before creating a, so to speak, “blanket” comment like that. Say a site has thousands of sprites used on every page, but one, and one that page a different sprite is used. Why on earth would you recommend that the huge file be loaded on this page that only needs one sprite?

      -1
  6. 8

    I’ve actually found a way to make sprites as I go that works for me:

    When I have a photoshop document of the design, I identify what pieces are probably going to be in the sprite (icons, arrows, etc…). I create a blank document that will be the basis of my sprite. It has a transparent background, and is usually like 100px wide by 1000px tall. I copy over the graphic elements over one at a time, and space them out vertically at the 100′s. So, if it’s the sixth item I’ve added, I move it to 600px down the PSD. Using the transform command (command-T), it’s easy to move things in an exact manner with the options in the upper toolbar area.

    That way, when I go to use the sprite in my css, I know I need to position things in increments of 100. When it comes to transparent PNGs, extra transparent space doesn’t really cost you anything. The only trick is if the target HTML element is taller than 100px tall – but I deal with that when it comes up.

    Also, to add new elements to the sprite is *easy* – just extend the PSD’s canvas downwards, and add new elements as you go. You don’t have to change your existing CSS if you work in this way.

    0
    • 9

      I work the same way!

      0
    • 10

      Lindsey - CSSgirl

      June 16, 2012 1:15 pm

      I’m totally stealing this method on all future projects. Makes so much damn sense :D

      0
      • 11

        I agree on making the sprite at the end of the project. That way you know every image should be placed correctly.

        I start off with a blank canvas, and go through my css for used images and drop them on the canvas. Then I start rearranging them to fit the canvas.

        First I place a guide on top and on the left of the canvas. Then for every image, I first select the image and then use the guide to snap to the image. Then with the ruler it’s easy to find the position.

        I actually make 2 sprites in general. One for all standard images and one for repeating images (> for example: repeat-y) > will not work in a usual sprite.

        0
  7. 12

    I love using the box-sizing trick too. It does cause some layout issues with some lightbox scripts, I noticed, so you’ll need to reset the box-sizing for those.

    0
  8. 14

    Nicely put about the sprites. Designing with sprites in mind is like deciding that your going to paint a canvas with just one kind of brush. Why impose the restrictions on the design right up front? I totally agree that optimization has its place, and I agree that it isn’t at the front of the line. :)

    Thanks Chris.

    0
  9. 15

    Awesome Q & A. I never knew about Gzipping CSS files, that will definitely become a new habit for me!

    0
  10. 16

    I’ll have to give border-box a shot. Should definitely be useful for responsive designing.

    Great article!

    0
  11. 17

    I found one small hiccup with global box-sizing and that was when I had already set percentages for padding in certain places on a project, that said it’ll likely find it’s way into any new job’s reset section.

    0
  12. 18

    For spriting, what you really should be looking at is a build system that can sprite automatically for you. That lets you develop the way Chris rightly emphasizes, without premature optimizations.

    Imagine that you could just save your images individually, thus having complete freedom to change the image or its dimensions. Further imaging that you wouldn’t have to think about image location for the spriting to work.

    Well, there are tools that do that for you, and more.

    I am using a build system called assetgraph-builder (https://github.com/One-com/assetgraph-builder) and my image optimization workflow goes like this:
    - Create my css and images as I normally would on a page where speed optimization is no issue.
    - Run the ‘buildProduction’ binary that assetgraph-builder provides with the ‘–optimizepngs’ switch

    Yes, no step 3!

    Well, except, it hasn’t really made any sprites at this point. It has however made data-uris of most of the smaller css images and inlined them so the need for spriting is almost gone.

    Ok, so I want spriting:
    - Add the following css property in the block with the background image you want sprited: ‘-one-sprite-group: myGroup;’ (you can have one or more sprite sheets based on your group names)
    - Run ‘buildProduction’ again.

    Yes, again no step 3!

    You now have a production build that gave you:
    - CSS and JS concatenation and minification
    - Inlined small css backgrounds (IE7 fallback to load pngs normally)
    - Sprited the images you wanted (with automated optimal packing)
    - Optional postoptimization of all pngs with pallette reduction if applicable, pngcrush and optipng
    - Renamed all assets to an md5-sum of their content for optimal long time caching
    - Optional CDN build
    - Optional appcache manifest
    - Much more that I probably forgot

    Why would you ever spend time thinking about spriting again?

    By the way, this also addresses the quistion on serverside css optimization. Run a static build system.

    0
  13. 20

    About the box-sizing, i use that since a long time ago in my job where the main supported browser was initially IE6 and i have been making changes to support the latest IE at each new release. If i remember correctly, IE7 and below will not have issues with this, since they may ignore the box-sizing, but the default box model on those browsers is actually border-box.

    0
  14. 21

    Another point should be noted that when using secure protocol spriting can drastically decrease page load times. In a past project when we were going into beta testing we switched to CSS spriting and our page load times decreased by 80%.

    0
  15. 22

    @Chip Cullen, re: “When it comes to transparent PNGs, extra transparent space doesn’t really cost you anything”

    The only downside is that the browser will render it as a bitmap which uses a surprising amount of memory. So in a mobile device that doesn’t have a lot of working memory the large size of the image will have some impact on browser performance.

    For example, if you have 30 items in your sprite it will be 100px × 3000px — a bitmap that takes up 878.9k in memory.

    Another option is to render the images as Data URIs. Some interesting reading on that here:
    •  http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/
    http://davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to

    0
    • 23

      @Paul – ah – I wasn’t aware of that. I was simply looking at file size, and didn’t think about how the browsers would interpret the image and it’s affect on machine memory. Thanks for the head’s up! (For what it’s worth, I crop the final version of the sprite down to just the pieces I’ve added, anyway.)

      0
  16. 24

    I disagree with you on your argument that sprinting should be done entirely at the end. If you have a good enough plan in th first place, sprinting from the beginning shouldn’t be a problem. Why build something with dozens of images, without planning for sprites from the beginning? I don’t want to go back and replace the code for all of my images. It’s wasted effort when you could do it only once from the beginning. Unless you’re working by the hour and trying to squeeze every last minute out of your work, I think that’s bad advice.

    0
  17. 25

    It’s always been strange that border and padding add to the width of an element. I have been using box-sizing for a while now, and I don’t think I could go back.
    Just started a new project, into which I have use put the * box-sizing into my CSS reset, so far its been brilliant.
    Even better is that now we are dropping IE 7 support, means I can use other nice things like inline-block.

    0
  18. 26

    I just reworked my own Grid system to allow for border-box sizing. For ie7 support, I found boxsizing.htc which seems to work really well. Not sure how the performance would be if using a universal selector (*). Personally, I have a class called “box” that I apply to elements that need it, usually only when nesting gridded elements.

    Anyway, good stuff to think about here.

    0
  19. 27

    In reference to your 1, 2, or 3 style sheets. Did I miss something, or don’t media queries require extra style sheets for device widths, etc?

    0
    • 28

      Patrick Samphire

      June 17, 2012 9:54 am

      There’s no need to use separate style sheets for different device widths. You can easily include the rules within a single style sheet using media queries.

      0
  20. 29

    When it comes to adding content to the triangle, why not just add only one more child element?

    Why the need for so much more markup?
    What am I missing?

    0
  21. 30

    Patrick Samphire

    June 17, 2012 9:59 am

    “There is no reason for CSS to be optimized for human readability. Strip out all non-relevant white space and comments.”

    Except that most of us learned our CSS by looking through stylesheets on sites we came across and figuring out how they had achieved the effect. If you remove whitespace and comments completely, you take that chance away from new developers.

    Admittedly, you can use something like Firebug to examine the styles, but it’s not the same as looking at a whole stylesheet and seeing how it works.

    I realize that we do want to optimize our sites, but we do, I think, still owe something to future developers, in the same way that other developers have helped us in the past. After all, no number of courses, books, or tutorials will ever be as useful as being able to see effective CSS in action on real sites. (Or, for that matter, seeing bad CSS being ineffective on real sites.)

    0
    • 31

      Great point!

      That’s why I always have my original CSS document available under the same URL, minus the .min part.

      So my actual CSS being served would be /path/to/file.min.css, but the original unminified CSS will always be view-able under /path/to/file.css

      0
      • 32

        Patrick Samphire

        June 18, 2012 1:54 am

        That’s an excellent idea. I think I’ll start doing that. (And I’m thinking that it might be worth me adding a comment somewhere (probably in the HTML) with a link to the unminified CSS to make it easy to find.)

        0
  22. 33

    Really thankful to Chris Coyier for giving this nice information’s about Box-Sizing and CSS Sprites.

    wordpress buddypress development

    0
  23. 34

    Well, yes, but my main concern are the users with css on but imaegs off, like me when I try to save the memory load of my Nokia phone browser. (I have not yet found a setting to disable also/only css on my phone)After all main navigation is quite essential part of the site usability.

    0
  24. 35

    thank you for such an awesome post.

    i always had problems with the boxes..from my next project onwards its gonna be box-sizing: border-box.

    1

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