meyerweb.com

Skip to: site navigation/presentation
Skip to: Thoughts From Eric

Border Imaging

As I dig into the nooks and crannies of the various CSS3 modules, I’ve come across something that seems like I should be able to do, but I can’t make it work in browsers.  Now, I know as well as anyone that if you try to do something and browsers won’t do it, it might well be the fault of the browsers.  Particularly if you can get various browsers to fail differently on the same declaration, as I have.  But this is, bizarrely, complicated enough that it’s hard to be sure if it’s me or them.

So allow me to pose this to you as a challenge.  Given the following ideal rendering, how would you arrive at the depicted result using the single 5-pixel-by-5-pixel image shown within the content?

Note that it doesn’t have to be quite as clean as this—if there are partial diamonds adjacent to the corners where repeated images get clipped, that’s fine.

Should you answer, please be clear which type of answer you’re giving:

  1. What the specification says you should write to make this happen.  Note to those tackling this fresh: I think the descriptive prose for border-image-slice (yes, -slice) makes this harder than it seems, but I could be wrong.
  2. What you wrote to get browsers to do it consistently.  (Safari, Firefox, and Opera at a minimum.  Did IE9 get border images yet?  Vendor prefixes not required unless you had to write different values for different browsers.)
  3. Both spec- and browser-friendly, which is of course what we really want.

I’m really curious to see if anyone cracks this one, because that person I will grill mercilessly until either I understand what’s happening or one of us starts plotting to have the other killed.

39 Responses»

    • #1
    • Comment
    • Mon 24 Jan 2011
    • 1448
    dominic wrote in to say...

    Hi Eric,

    As part of my site’s redesign I’ve elected to use the swanky new CSS property for border-images. Much to my initial dismay, there is no support for this in IE9 yet. IE visitors to my site will receive a different experience to those using Webkit/Gecko.

    One thing I found (in my implementation) was that I had to declare the border-width separately, in addition to the short-hand notation in the border-image declaration:

    border-top:18px;
    border-right:19px;
    border-bottom:46px;
    border-left:32px;

    border-image: url(main_imgBorder.png) 18 19 46 32 repeat;

    For the ‘slice’ that gets repeated along the top x-axis, this section of the image being used had to be 4px minimum in width for this to display correctly.

    In short, I think your original image needs to become a 15×15 image, with 9 repetitions of the original red dot (3 rows x 3 columns).

    I have encountered additional oddities in my implementation, which I will be writing up – once I’ve actually completed the site build!

    ttfn

    dominic

    • #2
    • Comment
    • Mon 24 Jan 2011
    • 1453
    Andy Clarke wrote in to say...

    As the implementations of border-radius use guides to slice up an image, I’m not sure if using just one, single 5x5px star image will work at all (it certainly didn’t for me). I have to admit that the border-image concept and terminology are confusing as they do suggest using a single image in a border space and not this slicing malarkey.

    Making a larger image with repeating areas was my only option. (See the image)

    This CSS works in Webkit and Firefox 4:

    .ihatetimvandamme {
    -moz-border-image : url(ihatetimvandamme.png) 5 round;
    -webkit-border-image : url(ihatetimvandamme.png) 5 round;
    border-image : url(ihatetimvandamme.png) 5 round;
    border-width : 5px; }

    Opera is a no-go no matter what I do, and I have no Windows running here so I can’t test IE9. Try changing the border-width property too. That’s fun.

    My five-minute result. I’m sure cleverer people know better?

    • #3
    • Comment
    • Mon 24 Jan 2011
    • 1503
    Peter Gasston wrote in to say...

    Having thought about this I’ve come to the conclusion that it isn’t so much that the syntax is at fault, but that the name of the property is misleading. What border-image does is slice an element up into four sides and four corners, and overlay those on the border of the element; really it’s framing the element,so perhaps changing the property name to border-frame would be more logical.

    If this were done, the border-image property could be changed to use a more simple syntax, which repeats an image around the element border (I’m sure that’s not as simple as I’ve made it sound). If this causes problems with backwards compatibility, perhaps another new property would have to be created (border-decoration?)

    • #4
    • Comment
    • Mon 24 Jan 2011
    • 1503
    Eric Meyer wrote in to say...

    Okay, so dominic and Andy both came to the same conclusion I did. I’m really hoping someone will pop in here to show us how we’re wrong, because otherwise this seems like a massively huge oversight in terms of simply supporting a simple and likely very common use of border images.

    • #5
    • Comment
    • Mon 24 Jan 2011
    • 1506
    Dave Krstin wrote in to say...

    I’m coming to the same conclusion as Mr Clarke as I had to create the same image.

    Although, I was able to get it to work in Firefox 3.6.13 and Opera 11. Of course it requires the vendor prefix.

    -o-border-image: url(‘diamond2.png’) 5 round round;

    IE9: no dice.

    • #6
    • Comment
    • Mon 24 Jan 2011
    • 1510
    Steve Lacey wrote in to say...

    As Andy said, the image he provided is the correct means of using border-radius.

    You simply have to imagine a 3×3 grid across the image, where the central vertical column and central horizontal row are what is repeated. Imagine your image being stretched out without corners being stretched or widths altered.

    The reason it is based on grid guides and not simply repeating the image I imagine is because designers usually want full control of the corners of the styled element.

    Whilst your scenario means that this adds complexity, having an option to enable the functionality you describe would require an additional flag on one of the functionalities assuming you don’t want to drop the current way it works.

    • #7
    • Comment
    • Mon 24 Jan 2011
    • 1512
    Eric Meyer wrote in to say...

    Peter, I agree with everything you said. This really is a shorthand way of creating a frame. The property name (actually all the related names) create a huge amount of confusion because they trigger expectations the actual behavior of the properties don’t meet.

    My guess is that it’s too late to change it, of course. I’ve been pointing out for years that background-origin is badly misnamed (and also blocking a feature which would suit the name far better) but my arguments have yet to impress the WG.

    • #8
    • Comment
    • Mon 24 Jan 2011
    • 1515
    Brandon wrote in to say...

    It looks like you do have to create an image that has repeating images for each side of the border. I see how having a single image repeat around the border would make logical sense for the border-image property, but it wouldn’t be as flexible.

    CSS3.info has a good example that shows different corner and side images.

    • #9
    • Comment
    • Mon 24 Jan 2011
    • 1521
    Philip Renich wrote in to say...

    That is a confusing part of the spec. With what the others said and Peter as well, it doesn’t sound like it should be chopping the image up into a grid. I see the usefulness of that, you only need one image. But if you just want to do a simple red-dotted border like Eric was showing, it’s way too complex for what is trying to be accomplished.

    At least at first glance it is, with the spec that big. Andy’s code is actually quite concise. Knowing you need to border-width looks key as well.

    • #10
    • Comment
    • Mon 24 Jan 2011
    • 1523
    Tab Atkins wrote in to say...

    Damn, went to lunch with the post ready to submit, and got scooped by everyone.

    The only thing you need to do is create a 15×15 image with 8 diamonds, then use “border-image: url(diamonds) 5 repeat;” (with the appropriate prefixes, currently).

    I don’t think complicating the border-image syntax with additional functionality to spam a single image to all 8 border regions is worthwhile, when you can so easily just turn that turn it into an 8-part image when you need this functionality.

    • #11
    • Comment
    • Mon 24 Jan 2011
    • 1527
    Jesse Gardner wrote in to say...

    Saw your post and whipped up something here, with varying degrees of success.

    I’m using the 5px by 5px image you specified, and it seems to work differently across different browsers.

    It renders almost correctly in Safari which seems to scale the repeating image down if the border size isn’t set at the end. With that set, it does render correctly.

    The border doesn’t render at all in Chrome unless the width is specified; once that’s set, it seems to render correctly.

    Firefox (3.6.1) doesn’t seem to play nicely, only displaying the diamonds in the corners, which is strange because Resig’s example seem to work. I suspect this is where the larger grid of diamonds would have to be used.

    I haven’t tried it in Opera or the others, but CSS3.info seems to be using the vendor-specific prefixes when showing off the demo for border-image, so it would be interesting to hear from someone how the others are rendering those demos.

    • #12
    • Comment
    • Mon 24 Jan 2011
    • 1528
    Stephanie (Sullivan) Rewis wrote in to say...

    Yes, I have found the same. When I teach, I liken it to 9-slice scaling in some graphics programs. It still makes my head spin. There’s a good article that has a little widget in it that allows you to change settings and watch the image change, but their domain apparently expired. :(

    On a site I’m working on currently, I found that even if I want the border only on one side, I had to actually make a 3×3 grid of circles (with the middle blank). Of course, that might just be my own ignorance that made me believe that. But it worked this way.

    Code looks like this:
    border-width: 0 0 18px 0;
    -moz-border-image: url(../img/border-image.gif) 18 repeat;
    -webkit-border-image: url(../img/border-image.gif) 18 repeat;
    border-image: url(../img/border-image.gif) 18 repeat;

    I really believe this is terribly named and confusing and like the border-frame idea.

    • #13
    • Comment
    • Mon 24 Jan 2011
    • 1537
    Tab Atkins wrote in to say...

    I wrote a blog post just now explaining the property: http://www.xanthir.com/blog/b49y0

    • #14
    • Comment
    • Mon 24 Jan 2011
    • 1545
    Louis wrote in to say...

    What’s even stranger is that if you use that 5×5 image in your example, and use following CSS:


    .example {
    border-width: 5px;
    -webkit-border-image: url(ihateandyclarke.png) 5 repeat;
    -moz-border-image: url(ihateandyclarke.png) 5 repeat;
    border-image: url(ihateandyclarke.png) 5 repeat;
    }

    … it works fine in WebKit (that is, it gets your desired result), but Firefox just puts the image in all 4 corners, with no repeating border. Nothing seems to fix it in Firefox.

    IE9 does not yet support border-image, so it’s a non-issue there.

    You’re absolutely right, though — there should be a way to just use a simple image that repeats, without having to worry about the 9 slices.

    Here’s an idea: Why don’t they add an extra property like border-image-type with two possible values: “standard” (which means the 9-slice method is used) and “simple” (which means the image is repeated naturally without the need for the 9 slices — as long as the border-width is set correctly to match the image’s width/height).

    I don’t think it would be too difficult to add this to what’s already in the spec, and to what’s already supported by the user agents.

    • #15
    • Comment
    • Mon 24 Jan 2011
    • 1546
    Eric Meyer wrote in to say...

    Tab, you don’t think that it’s worth supporting a case like the one I describe? You don’t think authors will be interested in repeating a single image all the way around an element without having to do Fireworks-style image slicing? Because I certainly do. Especially if the image is (optionally) rotated for each side. It would make alternate dash patterns very easy to accomplish, for example, along with many other things. The way it’s done now, drawing a frame, requires pixel counting and construction work.

    At the very least, changing the property names to use the word ‘frame’ would help prevent the confusion many of us seem to be experiencing. Whether that would make it border-frame-* or border-image-frame-* doesn’t much matter to me personally, but others might have stronger opinions.

    • #16
    • Comment
    • Mon 24 Jan 2011
    • 1547
    Todd wrote in to say...

    It’s only the shorthand that works correctly in the “standards-compliant” browsers. IE9 is not even close. Not every browser is going to understand the entire border-image syntax. Or at least that was my understanding when I last read the border-image property.

    I’m just left wondering how misused this will become and why we need to have all these new special CSS3 trinkets and baubles if CSS2.1 isn’t even finished yet.

    I think we’re heading back to the days where tables ruled layouts and those tables had gawdy and hideous tye-dyed or animated gif borders.

    • #17
    • Comment
    • Mon 24 Jan 2011
    • 1551
    Germán Martínez wrote in to say...

    Think I got something.
    I’m using:

    section p {
    padding: 5px 10px;
    -webkit-border-image: url(border-image-question.png) 100 repeat;
    border-width: 5px;
    }

    You can see the result in http://martinez.pe/meyerchallenge/ (webkit).

    What do you think?

    • #18
    • Comment
    • Mon 24 Jan 2011
    • 1609
    Eric Meyer wrote in to say...

    Awesome, Germán. Now: why does it work, and will it work in other browsers if you add the same declaration with their prefixes? I’d try it myself but your construction of the test makes it hard to copy locally.

    • #19
    • Comment
    • Mon 24 Jan 2011
    • 1609
    Tab Atkins wrote in to say...

    Eric, no, I don’t think that case is important enough to justify further complication to the syntax, when it’s *so easy* to just make an image that works witht he current syntax. You always have to balance functionality with ease-of-use. I think the current syntax is as far toward functionality as is practical, and is already dangerously confusing to use.

    Doing things like rotating the image for the sides makes the necessary complications to the syntax even more burdensome. Just make a larger image!

    • #20
    • Comment
    • Mon 24 Jan 2011
    • 1615
    Eric Meyer wrote in to say...

    Tab, I didn’t ask if it was worth complicating the syntax of border-iamge. I asked if it was worth supporting at all.

    I like your “just make a bigger image!” argument. That’s like “Why do you need advanced layout when it’s *so easy* to just use more floats?”. Not to mention the evidence in this comment thread that the property names as they exist now are confusing and cause people to assume that the case I described is easy to do, when it’s actually impossible.

    But as I intimated in a previous comment and you’re amply demonstrating here, the WG is not so much interested in changing things that are misleading or confusing to authors when they can instead pat authors on the head and tell them “there, there, just stop bringing your expectations to the table, do it our way, and you’ll be fine”.

    • #21
    • Comment
    • Mon 24 Jan 2011
    • 1617
    Jesse Gardner wrote in to say...

    I personally second your idea, Eric: border-frame-* for image grid-slicing functionality and border-image-* for simple image repeating.

    • #22
    • Comment
    • Mon 24 Jan 2011
    • 1625
    Tab Atkins wrote in to say...

    But… it’s *not* easy to just use more floats. Floats suck and are really painful and horrible. When there’s something that authors really want to do, but it’s really difficult, then we need to address it directly.

    Not *everything* needs the simplest possible solution, though. Going too far down that path produces an explosion of carefully-tailored solutions, which is counterproductive as you try and find the one that solves your particular problem. If it’s easy to get what you want by tweaking your approach and using an existing solution, then that’s probably the best thing to do. Hell, even if you *can’t* get exactly what you want, but you can get pretty close using an existing solution, it’s still probably best to say “use the existing solution”.

    In this case, just turning your one image into an 8-region image is completely trivial. It took me all of 20 seconds to do (not counting GIMP’s startup time). And by doing so, it’s then trivial to use with the existing solution (well, trivial once you’ve grokked the solution in the first place).

    And you then get things like rotating the images for each side *for free*, because you just bake that rotation into your image. Less spec work, less implementation work, less properties doing almost-but-not-quite-identical things for authors to learn.

    Seriously, I don’t understand why you’re pretending it’s hard to make a 15×15 image.

    (I have no particular opinion on the name; I don’t find -frame any more intuitive than -image, personally. But if you do, I suggest you bring it up on the mailing list asap.)

    • #23
    • Comment
    • Mon 24 Jan 2011
    • 1627
    dominic wrote in to say...

    In an age where we are striving to move towards a more semantic web, I think we will all agree that the current declaration is not the most intuitive (as evidenced by the array of confusion here). That said, the red dots are not to my tastes, but then that is a somewhat subjective viewpoint :-)

    • #24
    • Comment
    • Mon 24 Jan 2011
    • 1627
    Anton Peck wrote in to say...

    I ended up avoiding the border-image property and going with a single dot, multiple backgrounds, and a tiny bit of padding.


    background:
    url(./dot.png) 0 0 repeat-x,
    url(./dot.png) 0 0 repeat-y,
    url(./dot.png) 0 100% repeat-x,
    url(./dot.png) 100% 0 repeat-y;
    padding: .5em;

    • #25
    • Comment
    • Mon 24 Jan 2011
    • 1628
    Louis wrote in to say...

    Germán’s example will work with any value of 5 or higher for the offset (i.e. the “100” that he’s using is not necessary — just use Chrome’s developer tools to change it on the fly to “5” and it will not affect the output).

    But the same code (with -moz) still does not work in Firefox (in my testing), so I don’t think that’s a solution.

    • #26
    • Comment
    • Mon 24 Jan 2011
    • 1630
    dominic wrote in to say...

    * replace “the most intuitive” with “immediately obvious”

    • #27
    • Comment
    • Mon 24 Jan 2011
    • 1638
    Germán Martínez wrote in to say...

    You’re right Louis, that “100” is not necessary.
    I do think there must be a solution, but I guess it will be a hack.
    I’m trying to achieve the same thing in FF4 and Opera, no luck so far :(

    • #28
    • Comment
    • Mon 24 Jan 2011
    • 1731
    Germán Martínez wrote in to say...

    Eric,

    So far I have achieved to show the whole border in webkit but only two borders in Opera and FF (top & bottom or left & right).

    Maybe that’s a start and someone with more experience than me can finish the work.
    (there must be a way!)

    Here’s the code:

    section p {
    padding: 5px 10px;

    /* webkit: done */
    -webkit-border-image: url(border-image-question.png) 5 round;

    /* moz: ?? */
    -moz-border-image: url(border-image-question.png) 5 0 round;

    /* opera: ?? */
    -o-border-image: url(border-image-question.png) 5 0 round;

    border-image: url(border-image-question.png) 5 round;
    border-width: 5px;
    }

    The code is here: http://martinez.pe/meyerchallenge/

    • #29
    • Comment
    • Mon 24 Jan 2011
    • 1757
    Louis wrote in to say...

    Germán, that is quite interesting. The problem is, even if you were able to get it to work the same, it would be pointless unless the code was exactly the same for all browser.

    One of the rendering engines is doing something wrong here, and the spec doesn’t seem to indicate which one (although I haven’t examined it in enough detail to say for certain).

    • #30
    • Comment
    • Mon 24 Jan 2011
    • 1800
    Martin Sutherland wrote in to say...

    Here’s an alternative, using generated content to create nested artificial block-level elements inside the original paragraph: http://sunpig.com/martin/code/2011/borderimage/index.html

    Not quite what you were looking for, but it’s an amusing workaround. Works in FF, Chrome, Safari, and Opera; haven’t tried IE9.

    • #31
    • Comment
    • Mon 24 Jan 2011
    • 1805
    Emma Dobrescu wrote in to say...

    I think the real problem is that it was planned/implemented as a stretching background image. I remember trying it when it was implemented and being peeved with the fact that by default it would set the middle part of that image as the element’s background. You have to plan it carefully and draw pixels and calculate, because the algorithm is not the same and whatever might repeat – err, pardon me – stretch beautifully in WebKit, has many chances to be mismatched in Gecko. It reminds me of the so many image workarounds that were used along the time for shadows, rounded corners etc. I’ll admit that it encourages creativity. But whoever found this logical for a border has a very twisted mind. I don’t expect it to work with the same code in all browsers(and why should I, they are different pieces of software), but at least one way to make it work for each of them? Without pushing pixels around?

    • #32
    • Comment
    • Mon 24 Jan 2011
    • 1818
    Germán Martínez wrote in to say...

    Louis,

    I’m not sure about that, we are using different syntaxes already:

    -moz-border-radius-topright vs -webkit-border-top-right-radius

    That’s the advantage of vendor specific prefixes. We can achieve the same results using different syntaxes.

    Anyway, it was just an experiment ;)

    • #33
    • Comment
    • Mon 24 Jan 2011
    • 1853
    Eric Meyer wrote in to say...

    Well in that case, Tab, we should dump border-image and its related properties entirely because we can do just about everything it does with multiple backgrounds, as Anton demonstrated. And anything we can’t do could be addressed by adding just an extra property or two, not the six that border-image et al. require to do this very specific thing that can be accomplished by tweaking an existing solution. Right?

    Meantime, please don’t accuse me of pretending things I’m not, because it needlessly lowers the quality of the discussion. I’m not pretending it’s hard to create a 3×3 grid image. I’m saying that the property name makes it counterintuitive that you have to do that for this simple and likely common effect, and that even once you’ve gotten past that intuitive pothole it’s a bit annoying to have to do it for simple cases that could literally be handled with a single property. Which, if it were, would most appropriately called border-image. (Well, given CSS naming conventions. I’d personally find image-border more appropriate but it’d violate long-standing naming patterns.)

    • #34
    • Comment
    • Mon 24 Jan 2011
    • 2243
    will wrote in to say...

    Awesome demonstration! Border images are an excellent addition to CSS.

    For anyone trying to quickly achieve a dotted line around without having to worry about border madness, just use the “outline: ” property. I really think its a long-forgotten property, and slips right by internet explorer’s typical disasters.

    • #35
    • Comment
    • Tue 25 Jan 2011
    • 0631
    Louis wrote in to say...

    Germán, yes technically you’re correct, but when you have something like “5 0 round” for Mozilla and “5 round” for WebKit, that is not very future-proof. What will you put in the standard syntax (the one with no prefix, that’s supposed to be listed last)?

    Also, it should be noted here that “round”, AFAIK, is not supported by WebKit. WebKit treats “round” as “repeat”. “round” is supposed to prevent the repeated image from being clipped at the corners. In my testing, Firefox removes the clipping, but WebKit does not.

    • #36
    • Comment
    • Tue 25 Jan 2011
    • 0634
    Louis wrote in to say...

    Germán,

    Ah, pardon me. You’re referring to the difference in the longhand notation. In that case, you’re correct. I’m a little puzzled at why they’re doing that, but that’s another issue.

    But again that raises the question: What should we use for the standard syntax? Good point,though…

    • #37
    • Comment
    • Tue 25 Jan 2011
    • 0917
    Todd wrote in to say...

    When I tried using a 5×5 image, the corners would only show in FF 3.6.13 as well. Andy Clarke’s technique works well as was stated (Opera/IE9 – no). “Confused” is only one word I would describe how I am when dealing with border-image.

    Something so simple, yet so confusing. Why bother having border-image when it could be simplified and renamed?

    • #38
    • Comment
    • Tue 25 Jan 2011
    • 1014
    Eric Meyer wrote in to say...

    After some further thinking, I’ve posted about this on www-style. We’ll see if anything comes of it. Thanks to everyone who took a crack at this! Maybe I’ll start a series called “Complexquiz”.

    • #39
    • Comment
    • Fri 18 Feb 2011
    • 0604
    El Paso Web Design wrote in to say...

    Pretty neat effect, although I don’t want to endure the cross browser headache until *cough* IE at least displays CSS 2.0 decently ;)

Leave a Comment

Line and paragraph breaks automatic, e-mail address required but never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>



Remember to encode character entities if you're posting markup examples! Management reserves the right to edit or remove any comment—especially those that are abusive, irrelevant to the topic at hand, or made by anonymous posters—although honestly, most edits are a matter of fixing mangled markup. Thus the note about encoding your entities. If you're satisfied with what you've written, then go ahead...


January 2011
SMTWTFS
December February
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Sidestep

Feeds

Extras