Home > Back-end >  How do I create a CSS mixin using the new `part` syntax?
How do I create a CSS mixin using the new `part` syntax?

Time:10-18

I want to apply a number of CSS rules to different selectors, without creating additional selectors. In SCSS, this would be typically done with a mixin, eg:

@mixin gradient-text {
  color: transparent;
  background-clip: text;
  -webkit-background-clip: text;
  background-image: linear-gradient(
    350deg,
    var(--dark-blue),
    var(--teal),
    var(--bright-green)
  );
}

Reading around the internet, there's lots of references to the CSS apply syntax, but https://caniuse.com/sr_css-apply mentions:

@apply was briefly supported behind a flag in Chromium but has since been abandoned in favor of the ::part() selector.

Reading about CSS part though it seems like it's not possible to use CSS part without modifying my HTML and using web components, which have their own issues.

Is it possible to do a mixin in CSS, without modifying my HTML or JS, using part?

CodePudding user response:

According to the MDN article you linked to, ::part can only match elements within a shadow tree. Additionally, the spec for the ::part states

The ::part() pseudo-element only matches anything when the originating element is a shadow host.

Thus, if you wanted to leverage this pseudo-element for CSS mixins, you'd be better working with (developing) a native web component library. You may be able to use the corresponding part HTML attribute outside of the Shadow DOM to implement CSS mixins depending on your requirements.

When in doubt the best thing is to experiment. Here is an example of using ::part() and part (HTML attr) inside and outside of a shadow DOM. Best to test browser support on part as it is a relatively new technology. Moreover, seems there is still ongoing questions about how multiple ident's should be supported, if at all.

customElements.define('custom-thing', class CustomThing extends HTMLElement {
  constructor() {
    super()
    
    const root = this.attachShadow({ mode: 'closed'})
 
    root.append(document.getElementById('custom').content.cloneNode(true))
  }
})
[part~="a"] {
  color: red;
}
[part~="b"] {
  padding: 20px;
  background: gray;
}

p::part(a) {
  color: blue !important;
}

custom-thing::part(a) {
  color: green;
}
custom-thing::part(a)::after {
  content: 'A';
}
custom-thing::part(b) {
  color: orange;
}
custom-thing::part(a b) {
  /* does multiple ident values work? */
  color: blue;
}
<p part="a b">part</p>
<template id="custom">
  <style>
    p[part="a"] {
      color: aqua;
    }
  </style>
  <p part="a">part a</p>
  <p part="b">part b</p>
  <p part="a b">part a b</p>
</template>

<custom-thing></custom-thing>

  •  Tags:  
  • css
  • Related