Search code examples
htmlcssmix-blend-mode

Mix-blend-mode doesn't work if I use "transform" on the parent div


I want the text on the button to be 'transparent', so you can see the color below.

It's been almost 2 hours and I was going CRAZY trying to understand why it doesn't work, but I noticed that if I remove transform: translate(-50%, -50%); from its parent div it works. Why?

What am I doing wrong?

let button = document.querySelector('.button')
let body = document.querySelector('.body')

button.addEventListener('click', ()=> {
  let colorOne = parseInt(Math.random() * 255)
  let colorTwo = parseInt(Math.random() * 255)
  let colorThree = parseInt(Math.random() * 255)

  body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
  + ')'

  document.querySelector('.color').innerText = 'rgb (' + colorOne + ', ' + colorTwo + ', ' + colorThree
+ ')'})
.button {
  font-family: 'Poppins', sans-serif;
  border-radius: .5em;
  padding: .3em .7em;
  font-size: 1.1em;
  position: relative;
  background: white;
  mix-blend-mode: screen;
}

.color {
  font-family: 'Poppins', sans-serif;
  color: white;
  text-shadow: 1px 1px 3px black;
  letter-spacing: 1px;
}

.container {
  text-align: center;
  position: absolute;
  top: 50vh;
  left: 50vw;
  transform: translate(-50%, -50%);
}
<body class="body">
  
  <div class="container">
    <h3 class="button">Generate Colour</h3>
    <p class="color"></p>
  </div>
  
  <script src="main.js"></script>
</body>


Solution

  • It's a bit tricky to understand because you are facing two complex issues but change your code like below and it will work fine:

    let button = document.querySelector('.button')
    let body = document.querySelector('.body')
    
    button.addEventListener('click', ()=> {
      let colorOne = parseInt(Math.random() * 255)
      let colorTwo = parseInt(Math.random() * 255)
      let colorThree = parseInt(Math.random() * 255)
    
      body.style.background = 'rgb(' + colorOne + ', ' + colorTwo + ', ' + colorThree
      + ')'
    
      document.querySelector('.color').innerText = 'rgb (' + colorOne + ', ' + colorTwo + ', ' + colorThree
    + ')'})
    .button {
      font-family: 'Poppins', sans-serif;
      border-radius: .5em;
      padding: .3em .7em;
      font-size: 1.1em;
      position: relative;
      background: white;
    }
    
    .color {
      font-family: 'Poppins', sans-serif;
      color: white;
      text-shadow: 1px 1px 3px black;
      letter-spacing: 1px;
    }
    
    .container {
      text-align: center;
      position: absolute;
      top: 50vh;
      left: 50vw;
      transform: translate(-50%, -50%);
      mix-blend-mode: screen; /* the bleding on the parent element */
    }
    
    .body {
      min-height:100vh; /* full height since there is no in-flow content */
      margin:0;
      position:relative; /* the container need to be relative to body */
    }
    
    html {
      background:#fff; /* to stop background propagation from body to html */
    }
    <body class="body">
      
      <div class="container">
        <h3 class="button">Generate Colour</h3>
        <p class="color"></p>
      </div>
      
      <script src="main.js"></script>
    </body>