简体   繁体   中英

How to group the css selectors

:host([aspect-ratio='square']) img {
      aspect-ratio: var(--ratio-square);
    }
    :host([aspect-ratio='landscape']) img {
      aspect-ratio: var(--ratio-landscape);
    }
    :host([aspect-ratio='portrait']) img {
      aspect-ratio: var(--ratio-portrait);
    }
    :host([aspect-ratio='widescreen']) img {
      aspect-ratio: var(--ratio-widescreen);
    }
    :host([aspect-ratio='ultrawide']) img {
      aspect-ratio: var(--ratio-ultrawide);
    }
    :host([aspect-ratio='golden']) img {
      aspect-ratio: var(--ratio-golden);
    }

How can I make it to a single line? by reducing the duplicates of this code

I don't think you can reasonably do this with a single line.

You could do simplify it with Sass/Scss:

$ratios: "square", "landscape", "portrait", "widescreen", "ultrawide", "golden";

@each $ratio in $ratios {
    :host([aspect-ratio='#{$ratio}']) img {
      aspect-ratio: var(--ratio-#{$ratio});
    }
}

Which generates the CSS:

:host([aspect-ratio='square']) img {
    aspect-ratio: var(--ratio-square);
}

:host([aspect-ratio='landscape']) img {
    aspect-ratio: var(--ratio-landscape);
}

:host([aspect-ratio='portrait']) img {
    aspect-ratio: var(--ratio-portrait);
}

:host([aspect-ratio='widescreen']) img {
    aspect-ratio: var(--ratio-widescreen);
}

:host([aspect-ratio='ultrawide']) img {
    aspect-ratio: var(--ratio-ultrawide);
}

:host([aspect-ratio='golden']) img {
    aspect-ratio: var(--ratio-golden);
}

I can't think of any CSS only solution here. You'd basically need to be able to read the content of the attribute ( attr() should be able to do that), and then use it to compose a new CSS variable. This last step is more problematic, I don't think there is any way to compose strings in CSS and pass them to a func like var() .

I would have hoped for the new @property rule to allow us to do something around that, but when I tried to reference var(--css-var) values as syntax that simply failed (with no real surprises I must admit). And even if that did work, I'm not sure the attr() could have been used there either. attr() produces <string> and I don't think there is a way to convert a <string> to a variable name.

So the best I can think of as a CSS+HTML only solution is to modify your HTML code so that instead of doing

<my-elem aspect-ratio="square">content</my-elem>

You do

<my-elem style="--ratio:var(--ratio-square)">content</my-elem>

As you can see, that's a bit more character but stays relatively readable, and then your CSS can become

:host([style*="--ratio:"]) img { aspect-ratio: var(--ratio) }

 class MyElem extends HTMLElement { constructor() { super(); const style = document.createElement('style'); const img = new Image(); const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.appendChild(style); shadowRoot.appendChild(img); style.textContent = ` img { width: 150px; border: 1px solid; }:host([style*="--ratio:"]) img { aspect-ratio: var(--ratio); } `; } } customElements.define("my-elem", MyElem);
 :root { --ratio-square: 1/1; --ratio-landscape: 4/3; --ratio-golden: 1/1.618; }
 <my-elem style="--ratio:var(--ratio-square)"></my-elem> <my-elem style="--ratio:var(--ratio-landscape)"></my-elem> <my-elem style="--ratio:var(--ratio-golden)"></my-elem>

But given that you are in a ShadowDOM, you can actually keep that attribute and use your CustomElement's constructor to set the proper CSS variable at construct:

 class MyElem extends HTMLElement { constructor() { super(); const style = document.createElement('style'); const img = new Image(); const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.appendChild(style); shadowRoot.appendChild(img); const ratio = this.getAttribute("aspect-ratio"); style.textContent = ` img { width: 150px; border: 1px solid; }:host([aspect-ratio]) img { aspect-ratio: var(--ratio-${ratio}); } `; } } customElements.define("my-elem", MyElem);
 :root { --ratio-square: 1/1; --ratio-landscape: 4/3; --ratio-golden: 1/1.618; }
 <my-elem aspect-ratio="square"></my-elem> <my-elem aspect-ratio="landscape"></my-elem> <my-elem aspect-ratio="golden"></my-elem>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM