skip to Main Content

I’m implementing a set of classes for each letter of a word, and assigning each of them a transition-delay that is a multiple of the position of the letter.

For example:

<span class="char1">H</span>
<span class="char2">e</span>
<span class="char3">l</span>
<span class="char4">l</span>
<span class="char5">o</span>

And then each letter would be assigned a transition-delay like so:

.link:hover .char1 {
  transition-delay: 15ms;
}

.link:hover .char2 {
  transition-delay: 30ms;
}

.link:hover .char3 {
  transition-delay: 45ms;
}

.link:hover .char4 {
  transition-delay: 60ms;
}

Is there a way to write this more dynamically? I’m now rewriting this with React Styled Components and i wondered if there was a way to use the number that is present in the class name to calculate the transition-delay. So that there would only have to be one class definition, not several (as i’m turning this into a react component and i will not know how long the word would be).

This is how I would imagine this working in React:

const Link = styled.a`

   ...

  .char${num} {
    transition-delay: ${num*15}
  }

`

Where num is a whole positive integer

3

Answers


  1. Yes, CSS variables do now exist, and you can also use frameworks like SCSS (my favorite) or LESS!

    What you are wanting though would not really be possible with standard CSS variables, or at least not practical. My recommendation would be to use SCSS, and you can easily add SCSS to a react project if it’s not already part of your project.

    Your code could be converted to SCSS to do what you want like this and it will output your exact code:

    $delay: 15ms;
    
    @for $i from 1 through 4 {
      .link:hover .char#{$i} {
        transition-delay: $delay;
      }
      //increment delay
      $delay: $delay + $delay;
    }
    
    

    or

    $delay: 15ms;
    
    @for $i from 1 through 4 {
      .link:hover .char#{$i} {
        transition-delay: $delay * $i;
      }
    }
    

    or more likely a use case would be written as such to allow you to write styles for each selector individually

    .link {
      // styles for `.link` go here
    
      &:hover {
        //styles for `.link:hover` go here
    
        //Loop for all the `.link:hover .char*` elements
        $delay: 15ms;
        @for $i from 1 through 4 {
          .char#{$i} {
            transition-delay: $delay * $i;
          }
        }
      }
    }
    

    If you want to try it out, paste it here to see the compiled CSS result: https://sass.js.org/

    Login or Signup to reply.
  2. Depending on your styling approach, you could also use inline styles and JavaScript to dynamically compute CSS property values without SCSS. You can map over an array and use the index to compute the transitionDelay if an element is currently hovered over:

      const [hoverIndex, setHoverIndex] = React.useState(-1);
    
      return (
        <div>
          {'hello'.split('').map((char, index) => {
            const transitionStyles = hoverIndex === index ? {transitionDelay: `${(index+1) * 15}ms`} : {}
            return <span onMouseEnter={() => setHoverIndex(index)} onMouseLeave={() => setHoverIndex(-1)} style={transitionStyles}>{char}</span>
          })
          }    
        </div>
      );
    }
    

    Here is an example with font size:

    https://codesandbox.io/s/exciting-chaplygin-9czuhv?file=/src/App.js

    Login or Signup to reply.
  3. Because you asked if there is a way to write it more dynamically, yes there is. I do not think you can make it completely dynamic using only CSS but I think you can get halfway there from where you’re at.

    Instead of adding a separate class for each character, there is at least a way to use only a single class (shown below), making use of the nth-child pseudo-class selectors. Then all you’ll have to focus on is your CSS selectors:

    .link:hover > span:nth-child(1) {
      transition-delay: 15ms;
    }
    
    .link:hover > span:nth-child(2) {
      transition-delay: 30ms;
    }
    
    .link:hover > span:nth-child(3) {
      transition-delay: 45ms;
    }
    
    .link:hover > span:nth-child(4) {
      transition-delay: 60ms;
    }
    <a href="#" class="link">
      <span>H</span>
      <span>e</span>
      <span>l</span>
      <span>l</span>
      <span>o</span>
    </a>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search