CSS Variables via SVG data image

I can’t figure out how this is supposed to be done.
https://jsfiddle.net/2wtagnj9/

I did this part right I think, the fill part.

fill='var(--color-a)'
fill='var(--color-b)'
fill='var(--color-c)'
fill='var(--color-d)'

I think I messed up here.

:root {
 --color: var(--color-a,red);
 --color: var(--color-b,blue);
 --color: var(--color-c,green);
 --color: var(--color-c,orange);
}
body {
 background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='165' height='165' viewBox='0 0 165 165'><rect x='0' y='0' width='165' height='165' fill='var(--color-a)' /><rect x='5' y='5' width='160' height='160' fill='var(--color-b)' /><rect x='10' y='10' width='150' height='150' fill='var(--color-c)' /><rect x='15' y='15' width='140' height='140' fill='var(--color-d)' /><rect x='20' y='20' width='130' height='130' fill='var(--color-a)' /><rect x='25' y='25' width='120' height='120' fill='var(--color-b)' /><rect x='30' y='30' width='110' height='110' fill='var(--color-c)' /><rect x='35' y='35' width='100' height='100' fill='var(--color-d)' /><rect x='40' y='40' width='90' height='90' fill='var(--color-a)' /><rect x='45' y='45' width='80' height='80' fill='var(--color-b)' /><rect x='50' y='50' width='70' height='70' fill='var(--color-c)' /><rect x='55' y='55' width='60' height='60' fill='var(--color-d)' /><rect x='60' y='60' width='50' height='50' fill='var(--color-a)' /><rect x='65' y='65' width='40' height='40' fill='var(--color-b)' /><rect x='70' y='70' width='30' height='30' fill='var(--color-c)' /><rect x='75' y='75' width='20' height='20' fill='var(--color-d)' /><rect x='80' y='80' width='10' height='10' fill='var(--color-a)' /></svg>");
}

fill=“” is an html attribute that has nothing to do with css. There’s no point sticking css inside it.

You need to use either the style attribute inline or do it from css in the usual way.

Also your syntax is incorrect anyway.

See here for the proper format:

Actually I don’t think its possible (even if you got the syntax right) anyway as css variables won’t work inside a data uri. You’ll just have to specify the actual color in the normal way.

Can a background pattern be made with the svg in the html?

https://jsfiddle.net/xL0yaeg5/

<svg class="box" width="165" height="165" viewBox="0 0 165 165">
  <rect x="0" y="0" width="165" height="165" fill="teal" />
  <rect x="5" y="5" width="160" height="160" fill="black" />
  <rect x="10" y="10" width="150" height="150" fill="orange" />
  <rect x="15" y="15" width="140" height="140" fill="black" />
  <rect x="20" y="20" width="130" height="130" fill="teal" />
  <rect x="25" y="25" width="120" height="120" fill="black" />
  <rect x="30" y="30" width="110" height="110" fill="orange" />
  <rect x="35" y="35" width="100" height="100" fill="black" />
  <rect x="40" y="40" width="90" height="90" fill="teal" />
  <rect x="45" y="45" width="80" height="80" fill="black" />
  <rect x="50" y="50" width="70" height="70" fill="orange" />
  <rect x="55" y="55" width="60" height="60" fill="black" />
  <rect x="60" y="60" width="50" height="50" fill="teal" />
  <rect x="65" y="65" width="40" height="40" fill="black" />
  <rect x="70" y="70" width="30" height="30" fill="orange" />
  <rect x="75" y="75" width="20" height="20" fill="black" />
  <rect x="80" y="80" width="10" height="10" fill="teal" />
</svg>

I have never seen an svg written this way to make a pattern without it being in the css…

It has always been in a data image uri.

Adding this to the css didn’t work:

html,
body,
svg {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML is for content, and CSS for purely decorative stuff, so I’d have to ask you to think about whether your pattern actually belongs in HTML or not.

What did you expect it to do?

You have given your SVG a width and height of 165px, so setting the CSS to display at 100% means it will display at 165px.

background-repeat: repeat; in the css makes it repeat, but it’s in the html and not the css.

No you can’t do that I’m afraid except for the -moz only trick.

What was wrong with a background image that you had before or was it just that you were trying to use css variables to control the colors?

Can this SCSS be converted to root:?
https://jsfiddle.net/3smkg5p7/

$color-a: teal;
$color-b: black;
$color-c: orange;
$color-d: black;
@mixin element-color($color1, $color2, $color3, $color4) {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='165' height='165' viewBox='0 0 165 165' ><rect x='0' y='0' width='165' height='165' fill='#{$color1}' /><rect x='5' y='5' width='160' height='160' fill='#{$color2}' /><rect x='10' y='10' width='150' height='150' fill='#{$color3}' /><rect x='15' y='15' width='140' height='140' fill='#{$color4}' /><rect x='20' y='20' width='130' height='130' fill='#{$color1}' /><rect x='25' y='25' width='120' height='120' fill='#{$color2}' /><rect x='30' y='30' width='110' height='110' fill='#{$color3}' /><rect x='35' y='35' width='100' height='100' fill='#{$color4}' /><rect x='40' y='40' width='90' height='90' fill='#{$color1}' /><rect x='45' y='45' width='80' height='80' fill='#{$color2}' /><rect x='50' y='50' width='70' height='70' fill='#{$color3}' /><rect x='55' y='55' width='60' height='60' fill='#{$color4}' /><rect x='60' y='60' width='50' height='50' fill='#{$color1}' /><rect x='65' y='65' width='40' height='40' fill='#{$color2}' /><rect x='70' y='70' width='30' height='30' fill='#{$color3}' /><rect x='75' y='75' width='20' height='20' fill='#{$color4}' /><rect x='80' y='80' width='10' height='10' fill='#{$color1}' /></svg>");
}

html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}
body {
  @include element-color($color-a, $color-b, $color-c, $color-d);
}

There’s not much point because as mentioned before css variables cannot be used inside a data uri.

Mixins and include are SCSS anyway and would need to be compiled into normal css as there is no equivalent to them in css apart from the compiled css.

1 Like

This was an attempt.
https://jsfiddle.net/2n3zvwxh/

:root {
--color-a: teal;
--color-b: black;
--color-c: orange;
--color-d: black;
}

--variableSVGFill: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='165' height='165' viewBox='0 0 165 165'><rect x='0' y='0' width='165' height='165' fill='var(--color-a)' /><rect x='5' y='5' width='160' height='160' fill='var(--color-b)' /><rect x='10' y='10' width='150' height='150' fill='var(--color-c)' /><rect x='15' y='15' width='140' height='140' fill='var(--color-d)' /><rect x='20' y='20' width='130' height='130' fill='var(--color-a)' /><rect x='25' y='25' width='120' height='120' fill='var(--color-b)' /><rect x='30' y='30' width='110' height='110' fill='var(--color-c)' /><rect x='35' y='35' width='100' height='100' fill='var(--color-d)' /><rect x='40' y='40' width='90' height='90' fill='var(--color-a)' /><rect x='45' y='45' width='80' height='80' fill='var(--color-b)' /><rect x='50' y='50' width='70' height='70' fill='var(--color-c)' /><rect x='55' y='55' width='60' height='60' fill='var(--color-d)' /><rect x='60' y='60' width='50' height='50' fill='var(--color-a)' /><rect x='65' y='65' width='40' height='40' fill='var(--color-b)' /><rect x='70' y='70' width='30' height='30' fill='var(--color-c)' /><rect x='75' y='75' width='20' height='20' fill='var(--color-d)' /><rect x='80' y='80' width='10' height='10' fill='var(--color-a)' /></svg>");

html,
body {
  height: 100%;
  padding: 0;
  margin: 0;
}

body {
  
  var(--variableSVGFill);
}

I don’t know how I can say it any differently but custom variables don’t work in a data uri.

Even if it did work then you would fail here as already mentioned.

The ‘fill’ attribute is html and not part of css so CSS would never interact with it. You would have needed something like style=“fill:var(–color-a)”. However that still won’t work in a data uri and won’t be parsed by the css processor.

2 Likes

The issue with doing this with gradient is the size of the code.

What is the ‘size’ in this context?

This
https://jsfiddle.net/ab1mfx8u/

 body {
   background-image:
     linear-gradient(to bottom, teal 5px, #0000 5px),
     linear-gradient(to right, teal 5px, #0000 5px),

     linear-gradient(to bottom, black 10px, #0000 10px),
     linear-gradient(to left, black 5px, #0000 5px),
     linear-gradient(to top, black 5px, #0000 5px),
     linear-gradient(to right, black 10px, #0000 10px),

     linear-gradient(to bottom, orange 15px, #0000 15px),
     linear-gradient(to left, orange 10px, #0000 10px),
     linear-gradient(to top, orange 10px, #0000 10px),
     linear-gradient(to right, orange 15px, #0000 15px),

     linear-gradient(to bottom, black 20px, #0000 20px),
     linear-gradient(to left, black 15px, #0000 15px),
     linear-gradient(to top, black 15px, #0000 15px),
     linear-gradient(to right, black 20px, #0000 20px),

     linear-gradient(to bottom, teal 25px, #0000 25px),
     linear-gradient(to left, teal 20px, #0000 20px),
     linear-gradient(to top, teal 20px, #0000 20px),
     linear-gradient(to right, teal 25px, #0000 25px),

     linear-gradient(to bottom, black 30px, #0000 30px),
     linear-gradient(to left, black 25px, #0000 25px),
     linear-gradient(to top, black 25px, #0000 25px),
     linear-gradient(to right, black 30px, #0000 30px),

     linear-gradient(to bottom, orange 35px, #0000 35px),
     linear-gradient(to left, orange 30px, #0000 30px),
     linear-gradient(to top, orange 30px, #0000 30px),
     linear-gradient(to right, orange 35px, #0000 35px),

     linear-gradient(to bottom, black 40px, #0000 40px),
     linear-gradient(to left, black 35px, #0000 35px),
     linear-gradient(to top, black 35px, #0000 35px),
     linear-gradient(to right, black 40px, #0000 40px),

     linear-gradient(to bottom, teal 45px, #0000 45px),
     linear-gradient(to left, teal 40px, #0000 40px),
     linear-gradient(to top, teal 40px, #0000 40px),
     linear-gradient(to right, teal 45px, #0000 45px),

     linear-gradient(to bottom, black 50px, #0000 50px),
     linear-gradient(to left, black 45px, #0000 45px),
     linear-gradient(to top, black 45px, #0000 45px),
     linear-gradient(to right, black 50px, #0000 50px),

     linear-gradient(to bottom, orange 55px, #0000 55px),
     linear-gradient(to left, orange 50px, #0000 50px),
     linear-gradient(to top, orange 50px, #0000 50px),
     linear-gradient(to right, orange 55px, #0000 55px),

     linear-gradient(to bottom, black 60px, #0000 60px),
     linear-gradient(to left, black 55px, #0000 55px),
     linear-gradient(to top, black 55px, #0000 55px),
     linear-gradient(to right, black 60px, #0000 60px),

     linear-gradient(to bottom, teal 65px, #0000 65px),
     linear-gradient(to left, teal 60px, #0000 60px),
     linear-gradient(to top, teal 60px, #0000 60px),
     linear-gradient(to right, teal 65px, #0000 65px),

     linear-gradient(to bottom, black 70px, #0000 70px),
     linear-gradient(to left, black 65px, #0000 65px),
     linear-gradient(to top, black 65px, #0000 65px),
     linear-gradient(to right, black 70px, #0000 70px),

     linear-gradient(to bottom, orange 75px, #0000 75px),
     linear-gradient(to left, orange 70px, #0000 70px),
     linear-gradient(to top, orange 70px, #0000 70px),
     linear-gradient(to right, orange 75px, #0000 75px),

     linear-gradient(to bottom, black 80px, #0000 80px),
     linear-gradient(to left, black 75px, #0000 75px),
     linear-gradient(to top, black 75px, #0000 75px),
     linear-gradient(to right, black 80px, #0000 80px),

     linear-gradient(to left, teal 85px, #0000 85px);
   background-size: 165px 165px;
 }

There’s not a huge amount of code there as these things go. If you were working in a code editor like VSCode or similar, once created, you can collapse it down to a single line and forget about it whilst you work on other things.

Really, a single line, I don’t think that is possible.

I was curious and decided to try PHP to generate the CSS:

<?php declare(strict_types=1);

  $aBox   = [
      'black',  'orange',  'black',  'teal',
      'black',  'orange',  'black',  'teal',
      'black',  'orange',  'black',  'teal',
      'black',  'orange',  'black',
  ];  
  $BODY  = 'body {
              background-image:
              linear-gradient(to bottom, teal 5px, #0000 5px),
              linear-gradient(to right,  teal 5px, #0000 5px),
        ';
  $i2   = 5;
  $bg   = '#f000';
  FOREACH($aBox as $key => $item) :
    $i2  += 5;
    $i3   = $i2 -5;
    $BODY.= "
       linear-gradient(to bottom, $item {$i2}px, $bg {$i2}px),
       linear-gradient(to right,  $item {$i2}px, $bg {$i2}px),
       linear-gradient(to left,   $item {$i2}px, $bg {$i3}px),
       linear-gradient(to top,    $item {$i2}px, $bg {$i3}px),
    ";
  ENDFOREACH;
  $BODY .= 'linear-gradient(to left, teal 85px, #0000 85px);
           background-size: 165px 165px;
          }';

echo '<!DOCTYPE html><html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
<title> Title goes here </title>
<meta name="author"  content="John_Betong mailto:john@john-betong.tk ">
<style>' .$BODY .'</style>
</head>
<body>
</body>
</html>
';

Edit:

Upon reflection the colours are repeated and could use another internal foreach loop…

This is it (well, what fits on one screen) expanded in VSCode.

This is it collapsed as described above.
Screenshot 2021-08-15 at 17.16.51

If you want to see it fully expanded again, just click the ‘>’ carat to the left of where it says body. There’s a downward pointing one when it’s expanded in exactly the same place, but doesn’t show up until hovered over, which makes it awkward for getting a screenshot with it visible in.