CSS, background-repeat distance

fguillen picture fguillen · Jun 1, 2013 · Viewed 36.2k times · Source

I want to set a background-image but with an specific distance between the repetitions.

For example, I have this image to become a background-image:

enter image description here

And I want to fix the repetitions in a pattern like this:

enter image description here

Check the JSFiddle playground

I'm looking for a CSS3 clean solution, not JS, not extra elements, and so forth. If I have to use very modern CSS3 (un-supported) tricks is ok.

Answer

smnbbrv picture smnbbrv · Sep 15, 2015

I guess the ship has pretty much sailed, but still there is a solution based on data-URI.

You can generate an SVG containing your image which has a size greater than the image (e.g. to make the margin 60px just make a width equal to the width of the image (40px) + the desired margin (60px) = 100px):

The next step is embedding your image inside of the SVG:

<image width="40" height="40" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFVJREFUeNrs2EENgEAQBMGBoOOsgLQTgaB1dV9Cggf2Ua2g3r2te5xJrvSsjg83mwLnnuYBAgICAgICAgICAgICAgICAgICAgIC/tV7+St9L389AgwA9YgGfH7VrXwAAAAASUVORK5CYII=" />

And finally add this SVG as a background-image with the data URI:

#container {
    width: 300px;
    height: 100px;
    border: 1px solid #ccc;

    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="40"><image width="40" height="40" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFVJREFUeNrs2EENgEAQBMGBoOOsgLQTgaB1dV9Cggf2Ua2g3r2te5xJrvSsjg83mwLnnuYBAgICAgICAgICAgICAgICAgICAgIC/tV7+St9L389AgwA9YgGfH7VrXwAAAAASUVORK5CYII=" /></svg>');
    background-position: left center;
    background-repeat: repeat-x;
}

See the updated Fiddle.

One can say this is quite a big and dirty workaround. However this is a pure CSS solution which does not require creating of additional HTML elements / JavaScript. It has some disadvantages:

  1. You need to embed the image with the data-URI. This is probably not the thing you would like to do often.
  2. The solution looks a bit heavy.
  3. For IE9 you would need to encode the SVG as a URL.

Possible solution to all these problems is using CSS preprocessors, e.g. Sass. You can make a mixin, e.g.:

@mixin background-image-spaced($width, $height, $margin-right, $image) {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="#{$width + $margin-right}" height="#{$height}"><image width="#{$width}" height="#{$height}" xlink:href="data:image/png;base64,#{$image}" /></svg>');
}

body {
  @include background-image-spaced(40px, 40px, 60px, 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFVJREFUeNrs2EENgEAQBMGBoOOsgLQTgaB1dV9Cggf2Ua2g3r2te5xJrvSsjg83mwLnnuYBAgICAgICAgICAgICAgICAgICAgIC/tV7+St9L389AgwA9YgGfH7VrXwAAAAASUVORK5CYII=');
}

You can add here many things, e.g. all other margin values, you can encode the image to inject it instead of writing it manually using Compass, see e.g. this article to learn more about this process. This already looks way better and more comfortable to use.