Values of background shorthand property wrongly expanded when trying to call HTMLElement.style

94 Views Asked by At

In styles for an element I have a few inline CSS declarations including a shorthand declaration for background

<style>
  :root{
    --bg-white: rgba(255, 255, 255, 0);
  }
</style>

<div style="background: var(--bg-white); ... "></div>

but when iterating over HTMLElement.style the shorthand property looks like it's wrongly expanded

 for (const declaration of Array.from(target.style)) { 
   const value = target.style.getPropertyValue(declaration)

   console.log(`${declaration}: ${value}`)
 }

This should print out background-color: var(--bg-white) per HTMLElement.style documentation on MDN, but I get background-color: ''

Shorthand properties are expanded. If you set style="border-top: 1px solid black", the longhand properties (border-top-color, border-top-style, and border-top-width) are set instead.

Has anyone encountered this before?

2

There are 2 best solutions below

1
t.niese On BEST ANSWER

This should print out background-color: var(--bg-white) per HTMLElement.style documentation on MDN, but I get background-color: ''

If you use HTMLElement.style, it will return what is directly applied (not computed) through the styleattribute.

In that case the browser can't know what the var(...) in background: var(--bg-white); will resolve and to which background-... properties it will contain (The contents of the variable will be placed where the var(...) statement is and then the resulting value will be parsed.

So if you e.g. have --bg-white: content-box radial-gradient(crimson, skyblue); then your --bg-white will actually influence multiple properties.

3
Alexander Nenashev On

The problem that you use Array.from(target.style) to get a default iterator for target.style. It doesn't include the background property. According to the spec a shorthand property is expanded to its parts.

Everything is explained in the code.

Thanks to @t.niese for a tip in the comments.

<div id="test" style="background: var(--bg-white);">Test</div>

<script>

 const target = document.querySelector('#test');
 
 // style is itarable
 console.log(target.style[Symbol.iterator]);
 
 // but doesn't include background in the iterator
 console.log(...target.style);
 
 // but background is iterable!
 console.log(Object.getOwnPropertyDescriptor(target.style, 'background'));
 
 // we can see it in Object.keys
 console.log(Object.keys(target.style).filter(name => name === 'background'));
 
 // so we can iterate it anyway
 for(const k in target.style){
    if(k === 'background'){
      console.log(target.style[k]);
    }
 }
 
   // Object.entries works too
 console.log(Object.entries(target.style).filter(([name]) => name === 'background'));
 
 // or access directly
 console.log(target.style.getPropertyValue('background'));
 console.log(target.style.background);
 
</script>