Sliced and Diced Sandbags

by Rob Swan

44 Reader Comments

Back to the Article
  1. …just kidding actually :)

    Here’s yet another reason why inline styles have not been deprecated.

    Very neat trick. I wonder how this compares to the other technique of slicing the image into little pieces on-the-fly (performance-wise).

    Copy & paste the code below to embed this comment.
  2. …is actually easy to determine: In order to avoid too much div-containers, the height should be at least the font size + line height of the surrounding text. After all, there’s nothing between those lines.

    E.g. a font size of 1em and a line height of 1.5 would make a sandbag’s height of 1.5em.

    Just my two cents

    Copy & paste the code below to embed this comment.
  3. Is it possible to show the code as it’s delivered to the browser (especially the final version)?

    Copy & paste the code below to embed this comment.
  4. The problem you mention with Safari is mostly fixed with the latest Webkit, though there’s “other problems inherent”:http://bugzilla.opendarwin.org/show_bug.cgi?id=3998 . I don’t know when Apple plans on releasing Safari with this latest Webkit patch.

    Copy & paste the code below to embed this comment.
  5. John: You can view the pages as delivered to the browser from here:
    “www.fuelledoncoffee.com/tuition/sandbags/”:http://www.fuelledoncoffee.com/tuition/sandbags/
    (they’re the pages I used to generate the screenshots)

    Copy & paste the code below to embed this comment.
  6. How about using ajax to do your sandbagging, keeping the original markup free from all those divs and style attributes?

    Copy & paste the code below to embed this comment.
  7. Interesting. I wonder if it’s possible to do the same but use justified text, so it comes up to the actual edges of the sandbags; I think this would look much nicer. (I will have a go but will have to translate your efforts into ASP first)

    Copy & paste the code below to embed this comment.
  8. … but you CAN have 1px high DIV’s with no content in IE. IT doesn’t like the block to be empty – however IE is stupid enough to consider a remark as “something” and obey’s the height… For example: This (probably) wont work in IE:
    <div 1px”></div>
    but this will…
    <div 1px”><!——></div>

    Copy & paste the code below to embed this comment.
  9. How long does this code take to process? Just wondering with it being an interpreted language and if you had maybe 10 images like this on a page, reading each file from disc in order to work this out would take time? Or is this pre-processed?

    Nice idea though :)

    Copy & paste the code below to embed this comment.
  10. You can shorten the parts:
    div class=“sandbag-right” style=“background: url(an_image.png) -58px -60px no-repeat; width: 192px;

    By adding the parts:
    background-image: url(an_image.png);
    background-repeat: no-repeat;
    height: 30px;
    to the style-definition for the sandbag-right class in the header.

    That will leave the inline style:
    style=“background-position: -58px -60px; width: 192px;”

    And that’s a bit shorter :-)

    Copy & paste the code below to embed this comment.
  11. Great article, Rob, well done!

    In response to Paul’s comment on server load; it’s a fair point.  Pixel processing in GD isn’t the fastest.  However, it shouldn’t be hard to add some caching to the script.  Instead of using printf, sprintf to compile a string and write the final result to a final, say <image name>.cache.  Then when you call the alignedImage function, first see if there is a cache file for that image, if so just output the contents of the cache file else process the image.  Sure, it might still take time with the initial view of the page, but it’d be a lot faster on subsequent loads.

    Copy & paste the code below to embed this comment.
  12. Crud, there goes my tool “The Box Office”:http://www.theboxoffice.be/ (since May 2005) totally in the dark :(

    It does the same actually ;)

    Kindly,
    B!

    Copy & paste the code below to embed this comment.
  13. Kudos that’s a neat trick and would be dead easy to cache. Anyway I met you at Paolo’s wedding I’ll have to chase you for the photos? ;)

    Copy & paste the code below to embed this comment.
  14. Actually, it doesn’t go totally in the dark … The Box Office uses background color approximations, manual adjustment options, etc. Also handy for those who don’t run run PHP on their server or don’t know how to implement it in their current cms/blog.

    wbr,
    B!

    Copy & paste the code below to embed this comment.
  15. this is a really neat trick.  although, wouldn’t it be better for loading time if you just used the script once to generate the markup, then copy and paste the markup instead of calculating the sandbags dynamically?  i also think i agree with the line-height comment.  there’s no reason to split a sandbag in the middle of a line or in between lines.  nice job on this!

    Copy & paste the code below to embed this comment.
  16. Jeremy: You do have a good point about reducing the load time, although I think Andy Collington’s comment (see above) about using sprintf to cache the string would probably be better than manually copying and pasting the code (although that very same thought crossed my mind originally!).

    Christoph: I concur, working out the ‘correct’ sandbag height based on the line-height would be an excellent way of tackling the issue. Thanks for the comment, I’ll definitely utilise it.

    Dom: Small world! Drop me a mail and I can send you a link to the best of the wedding photos if Paolo hasn’t already shown you them.

    Copy & paste the code below to embed this comment.
  17. Good stuff! I think I’d tweak it, though, to seperate the alt and title parameters – so I can set one without the other. Mind you, I’d probably only use it for eye-candy images where both properties would be null anyway.

    Copy & paste the code below to embed this comment.
  18. How would I be able to use the line-height value in the php script?

    The only way I see fit is to manually input the line-height in the function call, but that means I would have to go into the code to change that value every time I decide to change the css. Not something for the believers in separation of code and presentation, eh?

    I’m not sure if javascript could pick out the current line height property for an element from the DOM, but even if it’s possible, I still can’t see how to use that value in the (server processed) php code.

    Any ideas?

    Copy & paste the code below to embed this comment.
  19. Anyone remember “this”:http://meyerweb.com/eric/css/edge/raggedfloat/demo.html ?

    Well I know it’s not quite the same thing, but it is from 4 and a half years ago.

    Copy & paste the code below to embed this comment.
  20. You know someone had to say this … while this is a neat concept, how is using a tool such as this semantically correct? Isn’t one of the points of ALA that we promote tools which are standards compliant? Also, I would argue that if your image conveys enough meaning that it requires alternative text, then using CSS to set it as a background image and using the title attribute is not sufficient because it will not be displayed if the image is not there, it will only create a tooltip.

    As a reminder, this tool does not take care of IE5-6’s poor handling of transparencies on PNGs. IE5-6 users will still see grayed text like they normally would. Works okay in IE7 (though, I did find that the text gets garbled for text below the medium font setting … and that using the Ctrl+scroolbutton scaled the entire page in the examples).

    Would it be too much to have an optional argument for the script that will let one set a default color to look for so that it doesn’t have to look for transparencies? This would make the script a bit more flexible in that it could work on JPGs for example.

    Copy & paste the code below to embed this comment.
  21. Referencing the question about using “AJAX” above, if you mean dHTML (dont know why you’d have to communicate with the server for something like this) I’ve got a solution that’s mostly done. It uses points outputted for imagemaps (yeah, I found a use for them) to generate the divs at load time inside a specified div or class of divs. I was considering submitting an article to ALA until this article came out. If there’s interest, I’ll put the code up somewhere for others to look at.

    Copy & paste the code below to embed this comment.
  22. I’m right with Brian on the semantics concerns.

    Copy & paste the code below to embed this comment.
  23. First of all i would like to say that it is a great article and it shows things I thought were not possible.

    But where would I use this? And how about all that extra code? Isn’t there a cleaner way to do it?

    Copy & paste the code below to embed this comment.
  24. Thanks for the idea. I have for long been familiar with the “demo”:http://meyerweb.com/eric/css/edge/raggedfloat/demo.html already mentioned in the comments, but this gave me a new idea: A script that slices an image automagically. Sure, it isn’t as convenient for the designer as this approach, but is friendlier for both the server and the page viewer.

    May I present, The “UnBlobifier”:http://www.abo.fi/~hpaul/unblobify.txt .

    Please be gentle, this is just a rough sketch of the script and also my first widely published source

    Copy & paste the code below to embed this comment.
  25. Great idea, but the article itself is let down by having no links to see each stage working, only the raw code. And no final demo link either! At least there is a link in the comments.

    I too echo the plea for the sandbags to fit the height of each text line. But what happens when the user increases the font size in real time?

    Readers may be interested to check out Stu Nicholls’ fantastic approaches to wrapping text around images on his site:

    1. http://www.cssplay.co.uk/menu/flow.html

    2. http://www.cssplay.co.uk/menu/embed.html

    Copy & paste the code below to embed this comment.
  26. It looks to me like this article uses the same technique as Stu Nicholls’ “fantastic approach to wrapping text around images”, except this article takes it a little further by automating the task of calculating element widths.

    Copy & paste the code below to embed this comment.
  27. The second line of text in the final results screenshot looks to be awfully close to the part of the graphic underneath it. As long as we’re calculating horizontal sandbag distances, shouldn’t we be ensuring the same margins vertically too? I assume this is a minor algorithmic addition to the PHP scan of the image.

    Copy & paste the code below to embed this comment.
  28. I will use a mix between the solution in this article and the old solution in curvelicious.

    Thanks for the inspiration!

    Copy & paste the code below to embed this comment.
  29. Hi Rob, just wanted to say this is a nice idea. I’ve avoided doing this kind of thing as it has traditionally involved a rather more static solution. I haven’t tried it yet but when I have a use for it I will certainly give it a go as I appreciate anything that allows a bit of creativity!

    Best of luck with fuelledoncoffee!

    ps Hi to Andy!

    Copy & paste the code below to embed this comment.
  30. Hi Rob,

    Good work on this. It was something I’d noticed was possible about a year ago, and since then worked on a class to do it all based on a png mask file. Works beautifully.

    Actually updated my site (www.leplop.com) back in April to showcase it. Certainly makes for a nice layout effect.

    I like the idea of using ajax to insert the code to improve the markup viewability.

    Anyways, props to you for also figuring it out! The more innovators out there, the better!

    Copy & paste the code below to embed this comment.
  31. On an accessiblity point, you used display:none for you fake alt text, which will be ignored by most screen readers. In terms of unnecessary markup, I agree with Niek Emmen about taking as much of the inline styling out as possible.

    But it is possible to position your image absolutely underneath the sandbags. I did this by putting the text inside the .sandbag-image div, an image tag inside the #example div but outside .sandbag-image, and making the following changes to the CSS:

    #example { width: 530px; position:relative }
    .sandbag-image { position:absolute; z-index:2 }
    #example img { position:absolute; top:20px; right:0; z-index:1 }

    I had to fiddle about with the vertical position of the image.

    This works in Firefox, Opera and IE6. Can’t test on Safari. This makes the alt text fully accessible. (There’s nothing to be done about those non-semantic divs).

    Copy & paste the code below to embed this comment.
  32. Kudos for working out a great and innovative new trick, Rob! I always enjoy it when ALA publishes a fun little “cool hack” article, as they fortunately seem to still be doing, from time to time.

    My main concern with your solution is that neither the image nor its ALT text is visible when CSS is disabled. If I were to use your script, I would update it to also output the image in a regular IMG tag, which would be set to display: none. This should allow for much better accessibility, without upsetting the sandbags at all.

    Copy & paste the code below to embed this comment.
  33. Looks like a very useful technique if one is prepared to accept the non-semantic divs.

    An optimisation could be introduced so that adjacent sandbags of the same size are replaced with a single sandbag with the height set appropriately, thus reducing the number of extra divs and therefore the time required for the page to load.

    Tolerances could be used so that adjacent, pre-optimisation, sandbags that are almost the same width are replaced also with a single sandbag that has its width set to the widest of the two.

    Of course deciding on which sandbags to combine could require a fair bit of computation, but if applied along with the earlier suggestion of caching of the results it would be a one-time hit and therefore acceptable.

    As regards setting the sandbag height according to the line-height, surely that would only be possible if font sizes are specified in pixels (generally to be avoided)?

    Copy & paste the code below to embed this comment.
  34. A while ago I used the shim technique on an experimental page (by hand).  But instead of using a background image in each sandbag, I used a negative margin on a DIV following them (you could use an image; in my case the image was purely presentational, so there was no need).  The page is “here”:http://www.freecog.net/2006/notebook/notebook.html .

    Henrik/The UnBlobifier: You probably shouldn’t include the alt text on each slice—someone using a screen-reader will hear it again and again!  Just putting it on the first one should be good enough.

    Copy & paste the code below to embed this comment.
  35. Always happy to read ALA’s articles, I’ve found a bad link on step four, it redirects me to a 404 page:

    - http://alistapart.com/d/sandbags/step4.php.txt

    Cheers,
    Giuseppe

    Copy & paste the code below to embed this comment.
  36. Wouldn’t using JavaScript instead favor a more semantic mark-up?

    Copy & paste the code below to embed this comment.
  37. Hey,
    I don’t have much more to say about the article, the result and wether or not this is a good ‘method’ for making image-aligned texts.
    But I don’t like the idea in general. I don’t see the benefits of text following the outline of an image. It just makes it harder to focus on the content and it doesn’t contribute to it. Sure it’s nice eye-candy and I can think of some very visual websites (think of an artists portfolio etc.) that would love this kind of thing. But then, very visual websites, usually don’t contain that many lines of text.

    kind regards,
    Mathijs

    Copy & paste the code below to embed this comment.
  38. Giuseppe:

    There is no link on example four.

    The text explains why:

    You don’t need to see the code for this, as it’s a minor tweak.

    Copy & paste the code below to embed this comment.
  39. how about we just nag browser developers to finally give us a standard method to achieve this easily.

    maybe using some css and an svg path and a few new css attributes

    div#puzzle {
    background:url(images/puzzle.jpg)
    clipping-source: url(masks/puzzlepiece.gif) alpha;
    /* will use black/white values of the gif/jpg to define rough outline*/
    clipping-source: url(masks/puzzlepiece.png);
    /* if transparent png is supported will use transparency value */
    clipping-source: url(masks/puzzlepiece.svg);
    /* if svg is supported will use vector path like DTP programs do */
    text-flow: left-clip;
    /* text will flow along shapes left side. If text were to the right it would be flat, if text-flow were ‘surround’ text would flow along all sides like in DTP programs*/
    }

    absurd wishful thinking, I know.

    Copy & paste the code below to embed this comment.
  40. Since absolute positioning takes the block out of the stack, couldn’t the image be positioned absolutely over the sandbags?

    Copy & paste the code below to embed this comment.
  41. Never mind, missed the post about this. My bad.

    Copy & paste the code below to embed this comment.
  42. You were all so happy to abandon the table layout “trick”. It validated nicely, but still: Not a correct use of the table-tag. And now you’re all at it again. Articles like this makes A List Apart a bit hypocritical, posing to be pro-standard good-gal/guy.

    Copy & paste the code below to embed this comment.
  43. Espen,

    Whilst I concur that this article isn’t coming from a 100% standards compliant stance, I still think that there’s room for ideas like this to be discussed on ALA without it becoming hypocritical.  I’d like to think of it as an ‘interesting’ approach to a problem.  I think we can be pro-standard and still have a little ‘fun’ every now and again ;)

    Copy & paste the code below to embed this comment.
  44. Hello Rob.

    First off, thank you for the well-written script. It is an effect I have been wanting to create on my site for a while, and just never got the guts to start writing a script. I had seen this effect done before on Mike Davidson’s website, and so I was aware of a “better” way to create this exact effect.

    So I wrote a new version of your script (a little more sloppy, so you can change it if you want). It seems to work in most browsers, but I couldn’t test in IE (windows) unfortunatly, but I doubt Mike would let anything go wrong in IE.

    You can read more at http://www.mcb.mcgill.ca/~jette/wordpress/2006/09/12/sandbags/

    Copy & paste the code below to embed this comment.