Search code examples
htmlcsstransition

CSS width transition not working when originally setting width to fit-content


I expect it has something to do with the width: fit-content property not being a number, but I don't know how to fix it without using a fixed width. As you can see below, the divs don't expand smoothly when hovered over. Instead, they expand to 100% instantly.

* {
  font-family: sans-serif;
}

div:not(#container) {
  width: fit-content;
  background-color: green;
  color: white;
  margin-top: 1em;
  padding: 1em;
  transition-property: width;
  transition-duration: 1s;
}

#ease {
  transition-timing-function: ease;
}

#linear {
  transition-timing-function: linear;
}

#ease-in {
  transition-timing-function: ease-in;
}

#ease-out {
  transition-timing-function: ease-out;
}

#in-out {
  transition-timing-function: ease-in-out;
}

#container:hover div {
  width: 90%;
}
<html>
  <head>
    <title>CSS animations</title>
  </head>
  <body>
    <div id="container">
      <div id="linear">
        <p>
          Linear
        </p>
      </div>
      <div id="ease">
        <p>
          Ease
        </p>
      </div>
      <div id="ease-in">
        <p>
          In
        </p>
      </div>
      <div id="ease-out">
        <p>
          Out
        </p>
      </div>
      <div id="in-out">
        <p>
          In-out
        </p>
      </div>
    </div>
  </body>
</html>


Solution

  • Your assumption/expectation about width: fit-content seems reasonable to me. Until someone can explain better, you could use width: fit-content along with min-width: 0, then animate min-width. It's not perfect, since the animation begins at 0 (you may notice a slight delay)

    * {
      font-family: sans-serif;
    }
    
    div:not(#container) {
      width: fit-content;
      min-width: 0;
      background-color: green;
      color: white;
      margin-top: 1em;
      padding: 1em;
      transition-property: min-width;
      transition-duration: 1s;
    }
    
    #ease {
      transition-timing-function: ease;
    }
    
    #linear {
      transition-timing-function: linear;
    }
    
    #ease-in {
      transition-timing-function: ease-in;
    }
    
    #ease-out {
      transition-timing-function: ease-out;
    }
    
    #in-out {
      transition-timing-function: ease-in-out;
    }
    
    #container:hover div {
      min-width: 90%;
    }
    <html>
      <head>
        <title>CSS animations</title>
      </head>
      <body>
        <div id="container">
          <div id="linear">
            <p>
              Linear
            </p>
          </div>
          <div id="ease">
            <p>
              Ease
            </p>
          </div>
          <div id="ease-in">
            <p>
              In
            </p>
          </div>
          <div id="ease-out">
            <p>
              Out
            </p>
          </div>
          <div id="in-out">
            <p>
              In-out
            </p>
          </div>
        </div>
      </body>
    </html>

    Related question, regarding height: fit-content