1

I know I can solve the problem below using <img /> and PHP (or javascript for that matter), but I'd like to solve it using just CSS, if I can.

I have marked up a language menu, in which I would like a flag icon to appear beside each named language.

Ideally, I would like to not have to add a new line to the CSS, every time I add a new language.

But is there any way - using attr() or CSS Custom Properties or some other method - that I can have the browser derive the correct background-image for each list item, using just (e.g.) class="fr" and data-language="fr"?

N.B. I am quite prepared for this to be beyond the current capabilities of CSS - but I am curious to find out if there is any inventive way of approaching this.

.language li {line-height: 40px;}
.language li::before {content:''; display:inline-block; position:relative; width:27px; height:27px; margin-right:9px; vertical-align:middle; background-color: rgb(191,191,191); border-radius:3px;}
.language li.de::before {background-image: url('/flags/de.png');}
.language li.en::before {background-image: url('/flags/en.png');}
.language li.es::before {background-image: url('/flags/es.png');}
.language li.fr::before {background-image: url('/flags/fr.png');}
<div class="language">
<h2>Select Language:</h2>
<ul>
<li class="en" data-language="en">English</li>
<li class="de" data-language="de">Deutsch</li>
<li class="es" data-language="es">Español</li>
<li class="fr" data-language="fr">Français</li>
</ul>
</div>


Additional Information:

My first approach was inadequate because it did not allow the flag icons to have rounded corners:

    .language li {
    background-position:0 center;
    background-size: 27px 27px;
    background-repeat: no-repeat;
    padding-left:36px;
    }
    
    .language li.de {background-image: url('/flags/de.png');}
    .language li.en {background-image: url('/flags/en.png');}
    .language li.es {background-image: url('/flags/es.png');}
    .language li.fr {background-image: url('/flags/fr.png');}
<div class="language">
<h2>Select Language:</h2>
<ul>
<li class="en" data-language="en">English</li>
<li class="de" data-language="de">Deutsch</li>
<li class="es" data-language="es">Español</li>
<li class="fr" data-language="fr">Français</li>
</ul>
</div>

But I am happy to skip the rounded corners if there is any potential here for achieving what I am aiming for.

5
  • I thought I should add the php tag because the question is most easily solved by using php and img. Is it wrong to include this tag? If you can explain why it's wrong, I will remove the php tag. Thank you, @Epodax. Commented Jul 25, 2016 at 12:18
  • You can probably fiddle around with attr() but doing it with JS will be simpler and more semantic. Commented Jul 25, 2016 at 12:19
  • 1
    I believe in sass, postcss or cssnext you could achieve this using variables, but I'm guessing you're looking for just a vanilla CSS approach. Commented Jul 25, 2016 at 12:29
  • 1
    No, this is not possible with basic CSS....you would need a preprocessor but that would just output the same CSS anyway, It would make easier to write but not any less verbose. Commented Jul 25, 2016 at 12:30
  • Possible duplicate of CSS set background-image by data-image attr Commented Jul 25, 2016 at 13:24

2 Answers 2

1

Currently, it is not possible without Javascript or any other programming language. Hopefully in the future we will be able to by using the attr() function, to get the attribute value from the element.

When using a pseudo-element, it gets the attribute from the original element. So you can do background-image: attr('data-bg' 'url') to get the data-bg attribute and treat it as a URL.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for that pointer, @Jerad! I see (from developer.mozilla.org/en-US/docs/Web/CSS/attr) that background-color:attr(data-language url, '/flags/eu/'); is definitely the (future) native CSS syntax for the kind of thing I am looking for.
You are most welcome, and keeping finger crossed. Hope it will available soon. :)
Yes. And wow. It's the worst supported CSS feature I've ever seen. See: caniuse.com/#feat=css3-attr .
0

For now, I have gone with:

CSS:

.language li img {
position:relative;
display:inline-block;
width:27px;
height:27px;
margin-right:9px;
vertical-align:middle;
border-radius:3px;
}

PHP:

<?php

for ($i = 0; $i < count($Language_Key); $i++) {

echo '
<li class="'.$Language_Key[$i].'">
<a href="/'.$Language_Page[$i].'/">
<img data-language="'.$Language_Key[$i].'" src="/flags/'.$Language_Key[$i].'.png" title="'.$Language_Name[$i].'" alt="Language Flag ('.$Language_Name[$i].')" />'.$Language_Name[$i].'
</a>
</li>
';

}

?>

but I'm still keen to hear of any innovative non-preprocessor approach, should there be a clever way to tackle this in native CSS.

(I'll concede that at the end of the day, none of this matters stupendously - it's all just an ongoing quest for elegantly marked-up documents).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.