CSS Variables (custom properties) in Pseudo-element “content” Property

后端 未结 4 1630
太阳男子
太阳男子 2020-12-14 01:44

Example use (what I want)

div::after {
  content: var(--mouse-x) \' / \' var(--mouse-y);
}

Test case showing it NOT working:

CodePe

相关标签:
4条回答
  • 2020-12-14 02:04

    content property only allows Strings, and since you are dealign with numbers and CSS cannot cast variables, you are left with the option to create another set of variables (from JS) which will serve as the printed values, and will be of type String.

    To set --mouse-x-text as String, it's not enough to cast it to that type using the old casting trick 2+"" = "2", but JSON.stringify is the only way what I know that can output a "real" string, out of the already-string value, which kind-of mean a string of a string, since CSS seems to strip the first string-layer.

    document.addEventListener('mousemove', ({clientX:x, clientY:y}) => {
      const {style} = document.documentElement
    
      style.setProperty('--mouse-x', x)
      style.setProperty('--mouse-y', y)
    
      // for printing
      style.setProperty('--mouse-x-text', JSON.stringify(x+""))
      style.setProperty('--mouse-y-text', JSON.stringify(y+""))
    })
    body::before{
      content: "X:"var(--mouse-x-text)"  Y:"var(--mouse-y-text);
    }

    0 讨论(0)
  • 2020-12-14 02:12

    Edit for clarity: CSS custom properties with a numerical value can be displayed in a pseudo-element's content property via a CSS counter.

    div {
        --variable: 123;
    }
    span:after {
        counter-reset: variable var(--variable);
        content: counter(variable);
    }
    <div>The variable is <span></span>.</div>

    .coordinates:before {
        counter-reset: x var(--x) y var(--y);
        content: 'The coordinates are (' counter(x) ', ' counter(y) ').';
    }
    <div class="coordinates" style="--x: 1; --y: 2"></div>


    Original Answer

    Got it to work using a hack involving CSS Counters. Enjoy.

    div::after {
      counter-reset: mouse-x var(--mouse-x, 245) mouse-y var(--mouse-y, 245);
      content: counter(mouse-x) " / " counter(mouse-y);
    }
    

    Full code in action:

    document.addEventListener('mousemove', (e) => {
      document.documentElement.style.setProperty('--mouse-x', e.clientX)
      document.documentElement.style.setProperty('--mouse-y', e.clientY)
      
      // output for explanation text
      document.querySelector('.x').innerHTML = e.clientX
      document.querySelector('.y').innerHTML = e.clientY
    })
    /* what I want!! */
    div::after {
      counter-reset: mouse-x var(--mouse-x, 245) mouse-y var(--mouse-y, 245);
      content: counter(mouse-x) " / " counter(mouse-y);
    }
    
    /* setup and presentation styles */
    div::before {
      content: 'mouse position:';
    }
    div {
      position: absolute;
      top: 0;
      left: 0;
      transform: translate(calc(var(--mouse-x, 245) * 1px), calc(var(--mouse-y, 327) * 1px));
      width: 10em;
      height: 10em;
      background: #ff3b80;
      color: #fff;
      display: flex;
      flex-flow: column;
      align-items: center;
      justify-content: center;
      border-radius: 100%;
      will-change: transform;
    }
    body {
      margin: 2em;
      font-family: sans-serif;
    }
    p {
      max-width: 50%;
      min-width: 25em;
    }
    <!-- test case: element with pseudo element -->
    <div></div>
    
    <!-- explanation (not test case) -->
    <main>
      <pre><code>div::after {
      content: var(--mouse-x) ' / ' var(--mouse-y);
    }</code></pre>
      <h1>If this worked...</h1>
      <p>
        We should see something like this: <b><span class="x">245</span> / <span class="y">327</span></b> updating with the mousemove coordinates inside the pseudo <i>::after</i> element for the div.
      </p>
    </main>

    0 讨论(0)
  • 2020-12-14 02:19

    I'm not quite sure if I understood your question correctly, but I think here's a solution...

    You can define a custom attribute to your <div> element.

    <div data-position></div>
    

    Then assign the position in this attribute with javascript:

      var position = e.clientX + " " + e.clientY
      document.querySelector("div").setAttribute('data-position', position)
    

    Finally use the attr() CSS function in the content property of your pseudoelement.

    div::after {
      content: attr(data-position);
    }
    

    And voila.


    Code Snippet:

    document.addEventListener('mousemove', (e) => {
      document.documentElement.style.setProperty('--mouse-x', e.clientX)
      document.documentElement.style.setProperty('--mouse-y', e.clientY)
      var position = e.clientX + "/" + e.clientY
      document.querySelector("div").setAttribute('data-position', position)
        // output for explanation text
      document.querySelector('.x').innerHTML = e.clientX
      document.querySelector('.y').innerHTML = e.clientY
    })
    /* what I want!! */
    
    div::after {
      content: attr(data-position);
    }
    /* setup and presentation styles */
    
    div::before {
      content: 'mouse position:';
    }
    div {
      position: absolute;
      top: 0;
      left: 0;
      transform: translate(calc(var(--mouse-x, 245) * 1px), calc(var(--mouse-y, 327) * 1px));
      width: 10em;
      height: 10em;
      background: #ff3b80;
      color: #fff;
      display: flex;
      flex-flow: column;
      align-items: center;
      justify-content: center;
      border-radius: 100%;
      will-change: transform;
    }
    body {
      margin: 2em;
      font-family: sans-serif;
    }
    p {
      max-width: 50%;
      min-width: 25em;
    }
    <div data-position></div>
    <span class="x"></span>/<span class="y"></span>

    0 讨论(0)
  • 2020-12-14 02:22

    You need quotation marks around the values of your custom properties.

    document.documentElement.style.setProperty('--mouse-x', "'" + e.clientX + "'")
    document.documentElement.style.setProperty('--mouse-y', "'" + e.clientY + "'")
    
    0 讨论(0)
提交回复
热议问题