104

I plan on building a custom photo gallery for a friend and I know exactly how I am going to be producing the HTML, however I am running into a small issue with the CSS.
(I would prefer to not have the page styling rely on jQuery if possible)


My question regards:
Data-Attribute in HTML
Background-image in CSS
I am using this format for my html thumbnails:
<div class="thumb" data-image-src="images/img.jpg"></div>

and I assume the CSS should look something like this:

.thumb {
    width:150px;
    height:150px;
    background-position:center center;
    overflow:hidden;
    border:1px solid black;

    background-image: attr(data-image-src);/*This is the question piece*/
}


My goal is to take the data-image-src from the div.thumb in my HTML file and use it for each div.thumb(s) background-image source in my CSS file.

Here is a Codepen Pen in order to get a dynamic example of what I am looking for:
http://codepen.io/thestevekelzer/pen/rEDJv

stephenkelzer
  • 1,234
  • 2
  • 12
  • 20

10 Answers10

74

You will eventually be able to use

background-image: attr(data-image-src url);

but that is not implemented anywhere yet to my knowledge. In the above, url is an optional "type-or-unit" parameter to attr(). See https://drafts.csswg.org/css-values/#attr-notation.

Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
70

If you wanted to keep it with just HTML and CSS you can use CSS Variables. Keep in mind, css variables aren't supported in IE.

<div class="thumb" style="--background: url('images/img.jpg')"></div> 
.thumb {
    background-image: var(--background);
}

Codepen: https://codepen.io/bruce13/pen/bJdoZW

  • 4
    This is probably the best answer at this moment. No javascript is always good. – Abdalla Arbab Oct 12 '19 at 07:23
  • +1. This is a more flexible solution than just adding the image directly inline as in another answer below, because you can declare multiple image paths for, say, multiple resolutions, and then decide in your CSS code which image to load for which resolution. – Sumit Nov 06 '20 at 06:07
  • 2
    at this point why not just set `background-image` in style attribute, why even bother with variable?? – Muhammad Umer Feb 11 '21 at 17:02
  • 1
    @MuhammadUmer I use background-image a lot too, just trying to fit the askers question as best as possible. Two benefits to using a variable I can think of off the top of my head are: 1) You can overwrite it more easily using CSS, not needing an !important. 2) You can setup default images in case the variable isn't set in :root{}. I updated my CodePen to illustrate these changes. – Bruce Brotherton Feb 12 '21 at 19:02
  • 1
    Also add `background-size: cover;` as per the @whitehawk comment if you want the image to fit properly. – SharpC Nov 02 '21 at 09:28
  • Just found a reason to set `background-image` directly: I don't know why but Chrome flickers the background image when I hover if I use the `background-image: var(--background)` method. – André Chalella May 14 '22 at 05:59
  • Beautiful. This allowed me to style pseudo-elements on the fly!!! – Rob May 26 '22 at 05:19
  • AWESOME... I'm giving a try right now – Ricardo Vigatti Feb 15 '23 at 19:24
18

It is not best practise to mix up content with style, but a solution could be

<div class="thumb" style="background-image: url('images/img.jpg')"></div>
Kevin Johne
  • 181
  • 1
  • 2
7

You will need a little JavaScript for that:

var list = document.getElementsByClassName('thumb');

for (var i = 0; i < list.length; i++) {
  var src = list[i].getAttribute('data-image-src');
  list[i].style.backgroundImage="url('" + src + "')";
}

Wrap that in <script> tags at the bottom just before the </body> tag or wrap in a function that you call once the page loaded.

Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
Jonathan
  • 8,771
  • 4
  • 41
  • 78
2

How about using some Sass? Here's what I did to achieve something like this (although note that you have to create a Sass list for each of the data-attributes).

/*
  Iterate over list and use "data-social" to put in the appropriate background-image.
*/
$social: "fb", "twitter", "youtube";

@each $i in $social {
  [data-social="#{$i}"] {
    background: url('#{$image-path}/icons/#{$i}.svg') no-repeat 0 0;
    background-size: cover; // Only seems to work if placed below background property
  }
}

Essentially, you list all of your data attribute values. Then use Sass @each to iterate through and select all the data-attributes in the HTML. Then, bring in the iterator variable and have it match up to a filename.

Anyway, as I said, you have to list all of the values, then make sure that your filenames incorporate the values in your list.

CodeFinity
  • 1,142
  • 2
  • 19
  • 19
  • 1
    This requires you to have a known list of values in your styles declaration. When I asked this question, I was attempting to have the markup drive what the styles displayed instead of the other way around. – stephenkelzer Oct 10 '17 at 21:40
  • 1
    Yeah, that’s tuff. Sorry! – CodeFinity Oct 10 '17 at 21:59
  • This helped me with a similar issue, and also showed me a Sass feature I didn't know existed, cheers! – MadSkunk Jun 14 '19 at 09:22
1

HTML

<div class="thumb" data-image-src="img/image.png">

jQuery

$( ".thumb" ).each(function() {
  var attr = $(this).attr('data-image-src');

  if (typeof attr !== typeof undefined && attr !== false) {
      $(this).css('background', 'url('+attr+')');
  }

});

Demo on JSFiddle

You could do this also with JavaScript.

Fritz
  • 173
  • 1
  • 6
  • 2
    Would `if (attr) {` get you in trouble? I don't see the point in the strict typeof and false checks, since both false and undefined are falsy values. – Thijs Koerselman Feb 08 '17 at 08:54
1

For those who want a dumb down answer like me

Something like how to steps as 1, 2, 3

Here it is what I did

First create the HTML markup

<div class="thumb" data-image-src="images/img.jpg"></div>

Then before your ending body tag, add this script

I included the ending body on the code below as an example

So becareful when you copy

<script>
var list = document.getElementsByClassName('thumb');

for (var i = 0; i < list.length; i++) {
  var src = list[i].getAttribute('data-image-src');
  list[i].style.backgroundImage="url('" + src + "')";
}
</script>

</body>
lupoll88
  • 150
  • 13
0

HTML CODE

<div id="borderLoader"  data-height="230px" data-color="lightgrey" data- 
width="230px" data-image="https://fiverr- res.cloudinary.com/t_profile_thumb,q_auto,f_auto/attachments/profile/photo/a54f24b2ab6f377ea269863cbf556c12-619447411516923848661/913d6cc9-3d3c-4884-ac6e-4c2d58ee4d6a.jpg">

</div>

JS CODE

var dataValue, dataSet,key;
dataValue = document.getElementById('borderLoader');
//data set contains all the dataset that you are to style the shape;
dataSet ={ 
   "height":dataValue.dataset.height,
   "width":dataValue.dataset.width,
   "color":dataValue.dataset.color,
   "imageBg":dataValue.dataset.image
};

dataValue.style.height = dataSet.height;
dataValue.style.width = dataSet.width;
dataValue.style.background = "#f3f3f3 url("+dataSet.imageBg+") no-repeat 
center";
0

Here is simple example using jQuery we can put the images in background

$('*[data-background-image]').each(function() {
    $(this).css({
        'background-image': 'url(' + $(this).data('background-image') + ')'
    });
});
div{
  height:200px;
  width:100% ;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div data-background-image="https://via.placeholder.com/500"> </div>
whitehawk321
  • 9
  • 1
  • 3
0

CSS3 Variables

HTML:

<div style="--thumbnail: url(https://example.com/images/source.png)"></div>

CSS:

&:after
{
  content: "";
  ...
  background-image: var(--thumbnail);
}