Reputation: 1
I realize there are similar questions but I haven't been able to find a proper explanation. I'm trying to understand best CSS practices for having multiple repeating backgrounds. Essentially I want to be able to repeat a background image to fit the entire height and width of the screen AND have another div centered inside of each repeating background image, but that inner-centered div should repeat only once per background image.
So below I have set a background image to fill the entire viewport and repeat. However, everything I've tried to do to have a the center image repeat has not worked. I end up with the inner image div repeating across the whole viewport as well as opposed to only repeating once per background image.
I know that I can just have a div with an img tag inside of it, style it however I want and then just copy + paste the div in HTML, but this is not DRY and I want to avoid that. I also know that you can declare multiple backgrounds with CSS3, but so far nothing has worked. I'm not sure if this is the right approach to this problem, but I find CSS to be really confusing for things of this nature. I'm not sure if there is a completely different and better way to do this so I appreciate any help at all, thanks
<div id='bground'>
<div id='center-image'></div>
</div>
<style>
#bground {
height:100vh;
width:100vw;
background-image: url(./img);
background-repeat: repeat;
}
#center-image {
???
}
<style>
Upvotes: 0
Views: 284
Reputation: 658
Image
If your intention is to repeat two images, one centered over top of the other, you can use an SVG for the centered image. Unfortunately, you will need to use a data URI for the centered image.
Essentially, you will use the SVG image as a container for the centered image. You need to make the SVG's width and height match the underlying image's dimensions. Then, the smaller image inside the SVG needs to be positioned so that it is centered relative to the underlying image. Notice the x, y, width, and height attributes on the image element within the SVG.
The example below uses multiple background images.
An answer on this question discusses the SVG approach in more detail: CSS, background-repeat distance
body {
margin: 0;
}
#bground {
height:100vh;
width:100vw;
background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%22200%22%20height%3D%22300%22%3E%3Cimage%20x%3D%2280%22%20y%3D%22130%22%20width%3D%2240%22%20height%3D%2240%22%20xlink%3Ahref%3D%22data%3Aimage%2Fjpeg%3Bbase64%2C%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj%2F2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj%2FwgARCAAoACgDASIAAhEBAxEB%2F8QAGwAAAwEAAwEAAAAAAAAAAAAAAAQGAwECBQf%2FxAAXAQADAQAAAAAAAAAAAAAAAAABAgMA%2F9oADAMBAAIQAxAAAAG86acOV1s9MqB6A8n5WklJX%2Be1spUAXYuMNlgBjUw09AMf%2F8QAIRAAAgICAQQDAAAAAAAAAAAAAgMAAQQRBQYQEiETFBX%2F2gAIAQEAAQUClwpcZ77%2FAGkk%2BtHPCbqc3ksWJUW%2Bn8mwO2rnqc0L4T23fAibGWIQj1LbUyFoXkDmfFP0jn%2F%2FxAAZEQACAwEAAAAAAAAAAAAAAAAAAQMQESD%2F2gAIAQMBAT8BGOPecr%2F%2FxAAYEQEBAQEBAAAAAAAAAAAAAAAAARAREv%2FaAAgBAgEBPwFHpUzqXP%2FEACMQAAEDAwMFAQAAAAAAAAAAAAEAAiEDEBESMTIEE0FxkSD%2F2gAIAQEABj8C%2FZpNqDWPCg59XDKOZE4WxTqL4aZGVzb9sH9PqAAnSubvqfUe7LBGCthaV3GjfwiGDHq3%2F8QAHhAAAgICAwEBAAAAAAAAAAAAAAERITFBEFFhkXH%2F2gAIAQEAAT8haky4Yk6rhk9ldiBK0xsVPRDcN4kl5b%2BG6dVLEs%2FIN9V8Hk4zXQWCcOpK2NluSVmRnNR6PKc26JjoircsTUz%2F2gAMAwEAAgADAAAAEDOwo1gwYfv%2FxAAYEQEBAQEBAAAAAAAAAAAAAAABABEQYf%2FaAAgBAwEBPxC8yLXuss6dbL%2F%2FxAAYEQEAAwEAAAAAAAAAAAAAAAABABARMf%2FaAAgBAgEBPxCgDk3lNiiJX%2F%2FEACEQAQACAgIBBQEAAAAAAAAAAAEAESExQVFxEGGBobHR%2F9oACAEBAAE%2FELW0gqmyDDiYrR5lZuXo9KVbULukWV5B0pzUsrFUqlmyGZMLEtl8wBS6zwWtmuZz55VQ3LMSNlQbLcZilBff%2B0RlvhzNRXR3Q52y0I1bVzNQpLb5p6gGyHhB%2FZtwQwhRpbIkobZnuBFUklgL3Eiln3P%2F2Q%3D%3D%22%20%2F%3E%3C%2Fsvg%3E'), url('https://unsplash.it/200/300/?random');
/*
SVG image before URL encoding (required for IE/Edge)
data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="300"><image x="80" y="130" width="40" height="40" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAAoACgDASIAAhEBAxEB/8QAGwAAAwEAAwEAAAAAAAAAAAAAAAQGAwECBQf/xAAXAQADAQAAAAAAAAAAAAAAAAABAgMA/9oADAMBAAIQAxAAAAG86acOV1s9MqB6A8n5WklJX+e1spUAXYuMNlgBjUw09AMf/8QAIRAAAgICAQQDAAAAAAAAAAAAAgMAAQQRBQYQEiETFBX/2gAIAQEAAQUClwpcZ77/AGkk+tHPCbqc3ksWJUW+n8mwO2rnqc0L4T23fAibGWIQj1LbUyFoXkDmfFP0jn//xAAZEQACAwEAAAAAAAAAAAAAAAAAAQMQESD/2gAIAQMBAT8BGOPecr//xAAYEQEBAQEBAAAAAAAAAAAAAAAAARAREv/aAAgBAgEBPwFHpUzqXP/EACMQAAEDAwMFAQAAAAAAAAAAAAEAAiEDEBESMTIEE0FxkSD/2gAIAQEABj8C/ZpNqDWPCg59XDKOZE4WxTqL4aZGVzb9sH9PqAAnSubvqfUe7LBGCthaV3GjfwiGDHq3/8QAHhAAAgICAwEBAAAAAAAAAAAAAAERITFBEFFhkXH/2gAIAQEAAT8haky4Yk6rhk9ldiBK0xsVPRDcN4kl5b+G6dVLEs/IN9V8Hk4zXQWCcOpK2NluSVmRnNR6PKc26JjoircsTUz/2gAMAwEAAgADAAAAEDOwo1gwYfv/xAAYEQEBAQEBAAAAAAAAAAAAAAABABEQYf/aAAgBAwEBPxC8yLXuss6dbL//xAAYEQEAAwEAAAAAAAAAAAAAAAABABARMf/aAAgBAgEBPxCgDk3lNiiJX//EACEQAQACAgIBBQEAAAAAAAAAAAEAESExQVFxEGGBobHR/9oACAEBAAE/ELW0gqmyDDiYrR5lZuXo9KVbULukWV5B0pzUsrFUqlmyGZMLEtl8wBS6zwWtmuZz55VQ3LMSNlQbLcZilBff+0RlvhzNRXR3Q52y0I1bVzNQpLb5p6gGyHhB/ZtwQwhRpbIkobZnuBFUklgL3Eiln3P/2Q==" /></svg>
*/
}
<div id="bground">
</div>
Arbitrary Content
If your intention is to have your inner div contain arbitrary content, then you must use either a server-side solution or client-side script.
Here's a solution that uses html2canvas to convert your div into an image. The image is then inserted into an SVG like the example above.
var repeats = document.getElementsByClassName('background-repeat-centered');
for (var i = 0, max = repeats.length; i < max; i++) {
var repeat = repeats[i],
measureImage = new Image(),
parentImage = repeat.parentElement,
parentImageStyle = parentImage.currentStyle || window.getComputedStyle(parentImage, false),
parentImageSrc = parentImageStyle.backgroundImage;
measureImage.src = parentImageSrc.replace(/url\((['"])?(.*?)\1\)/gi, '$2').split(',')[0];
measureImage.addEventListener('load', function () {
var parentWidth = measureImage.width,
parentHeight = measureImage.height;
html2canvas(repeat, {
onrendered: function(canvas) {
var repeatWidth = canvas.width,
repeatHeight = canvas.height,
x = (parentWidth - repeatWidth) / 2,
y = (parentHeight - repeatHeight) / 2;
repeat.parentElement.style.backgroundImage = 'url(\'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' + parentWidth + '" height="' + parentHeight + '"><image x="' + x + '" y="' + y + '" width="' + repeatWidth + '" height="' + repeatHeight + '" xlink:href="' + canvas.toDataURL() + '" /></svg>') + '\'), ' + parentImageSrc;
}
});
}, false)
}
.background-repeat-centered {
visibility: hidden;
}
body {
margin: 0;
}
#bground {
height: 100vh;
width: 100vw;
background-image: url('http://lorempixel.com/200/300/');
}
#sample {
background: Purple;
color: White;
display: inline-block;
font-family: sans-serif;
font-weight: bold;
padding: 10px;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<div id="bground">
<div class="background-repeat-centered" id="sample">
Repeat after me!
</div>
</div>
Upvotes: 1