Search code examples
htmlcsscss-transforms

How to make a 3D element with an extrude effect?


I created an isometric 10x10 field with:

transform : rotateX(60deg) rotateY(0deg) rotateZ(-45deg)

teste

Is there any property that modifies divs "z-heigth", allowing me to give each of the inner cells a different "depth", creating a column?

Cell and Table current code:

#table {
  width: 600px;
  height: 600px;
  background-color: white;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  transform: rotateX(60deg) rotateY(0deg) rotateZ(-45deg)
}

#table>DIV {
  width: 58px;
  height: 58px;
  background-color: #ffffff;
  border: 1px solid grey;
}
<div id="table">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>


Solution

  • You can use some perspective and transform. Don't forget to add transform-style:preserve-3d; to the parent element

    #table {
      width: 600px;
      height: 600px;
      background-color: white;
      display: flex;
      flex-wrap: wrap;
      transform: rotateX(60deg) rotateY(0deg) rotateZ(-45deg);
      transform-style:preserve-3d; /* this is important */
    }
    
    #table > * {
      width: 58px;
      height: 58px;
      background-color: pink;
      border: 1px solid grey;
    }
    
    div:nth-child(50) {
      transform:perspective(100px) translateZ(30px);
    }
    /* or without perspective */
    div:nth-child(10) {
      transform:translateZ(30px);
    }
    <div id="table">
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    </div>

    Also like below by adding pseudo element to create 'walls'

    #table {
      width: 600px;
      height: 600px;
      background-color: white;
      display: flex;
      flex-wrap: wrap;
      transform: rotateX(60deg) rotateY(0deg) rotateZ(-45deg);
      transform-style:preserve-3d; /* this is important */
    }
    
    #table > * {
      width: 58px;
      height: 58px;
      background-color: pink;
      border: 1px solid grey;
    }
    
    div:nth-child(7n + 3) {
      transform:translateZ(58px);
      transform-style:preserve-3d; /* this is important */
    }
    div:nth-child(7n + 3)::before,
    div:nth-child(7n + 3)::after{
      content:"";
      position:absolute;
      top:0;
      left:0;
      right:0;
      bottom:0;
      background:inherit;
      border:inherit;
    }
    div:nth-child(7n + 3)::before {
      transform-origin:left;
      transform:rotateY(90deg);
    }
    div:nth-child(7n + 3)::after {
      transform-origin:bottom;
      transform:rotateX(90deg);
    }
    <div id="table">
      <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    </div>

    To make it generic we can add some CSS variables:

    #table {
      width: 600px;
      height: 600px;
      background-color: white;
      display: flex;
      flex-wrap: wrap;
      transform: rotateX(60deg) rotateY(0deg) rotateZ(-45deg);
      transform-style:preserve-3d; /* this is important */
    }
    
    #table > * {
      width: 58px;
      height: 58px;
      background-color: pink;
      border: 1px solid grey;
    }
    
    div[style*='--d'] {
      transform:translateZ(var(--d));
      transform-style:preserve-3d; /* this is important */
    }
    div[style*='--d']::before,
    div[style*='--d']::after{
      content:"";
      bottom:0;
      left:0;
      position:absolute;
      background:inherit;
      border:inherit;
    }
    div[style*='--d']::before {
      width:var(--d);
      top:0;
      transform-origin:left;
      transform:rotateY(90deg);
    }
    div[style*='--d']::after {
      height:var(--d);
      right:0;
      transform-origin:bottom;
      transform:rotateX(90deg);
    }
    <div id="table">
      <div></div><div></div><div></div><div></div><div></div><div style="--d:150px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div style="--d:70px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div style="--d:20px;"></div><div></div><div></div><div></div><div></div><div style="--d:40px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div  style="--d:100px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    </div>

    CSS 3D columns

    Some animation for the fun:

    #table {
      width: 600px;
      height: 600px;
      background-color: white;
      display: flex;
      flex-wrap: wrap;
      transform: rotateX(60deg) rotateY(0deg) rotateZ(-45deg);
      transform-style:preserve-3d; /* this is important */
    }
    
    #table > * {
      width: 58px;
      height: 58px;
      background-color: pink;
      border: 1px solid grey;
    }
    
    div[style*='--d'] {
      transform:translateZ(var(--d));
      animation:a 2s linear infinite alternate;
      transform-style:preserve-3d; /* this is important */
    }
    div[style*='--d']::before,
    div[style*='--d']::after{
      content:"";
      bottom:0;
      left:0;
      position:absolute;
      background:inherit;
      border:inherit;
      animation:inherit;
    }
    div[style*='--d']::before {
      width:var(--d);
      top:0;
      animation-name:c;
      transform-origin:left;
      transform:rotateY(90deg);
    }
    div[style*='--d']::after {
      height:var(--d);
      right:0;
      animation-name:b;
      transform-origin:bottom;
      transform:rotateX(90deg);
    }
    
    @keyframes a {
      from {
        transform:translateZ(0);
      }
    }
    @keyframes b {
      from {
        height:0px;
      }
    }
    @keyframes c {
      from {
        width:0px;
      }
    }
    <div id="table">
      <div></div><div></div><div></div><div></div><div></div><div style="--d:150px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div style="--d:70px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div style="--d:20px;"></div><div></div><div></div><div></div><div></div><div style="--d:40px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div  style="--d:100px;"></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
    </div>