Search code examples
htmlcsscss-shapescss-transforms

Perfect horizontally sqeezed diamond flow chart symbol using div tag


I would like to use CSS3 transform to squeeze a <div> to a perfect flow chart decision symbol.

Here's a fiddle

My CSS

.diamond {
  top: 100px;
  left: 100px;
  height: 75px;
  width: 200px;
  position: absolute;
  border: solid 1px black;
          transform: skewX(-46deg) skewY(-11deg) scaleY(0.5) rotate(45deg);
  -webkit-transform: skewX(-46deg) skewY(-11deg) scaleY(0.5) rotate(45deg);
}

But I could not make the two left right tips exactly horizontal and top bottom tips exactly vertical.


Solution

  • If you want to create a perfect diamond shape (flow-chart decision symbol) then you must scale the Y axis first to make the height of the element match its width and then just apply rotate transformation. The other transforms are not really required. Remember that scale must be done prior to rotate (so, it must be added on the right of the rotate).

    .diamond {
      top: 100px;
      left: 100px;
      height: 75px;
      width: 200px;
      position: absolute;
      border: solid 1px black;
      border-width: 1px 3px;
      transform-origin: left center;
      transform: rotate(45deg) scaleY(2.667);
    }
    <div class="diamond"></div>

    The above demo produces a normal diamond. If you want the diamond to look squeezed along Y axis then you could just add an extra scaleY() after the rotate to crush/squeeze the height of the diamond alone. The key point is to always scale the Y axis first to make the height and width match the other.

    .diamond {
      top: 100px;
      left: 100px;
      height: 75px;
      width: 200px;
      position: absolute;
      border: solid 1px black;
      border-width: 1px 3px;
      transform: scaleY(0.5) rotate(45deg) scaleY(2.667);
    }
    <div class="diamond"></div>

    If you want to squeeze the X axis, apply the reduction scale on X axis instead of Y axis.

    .diamond {
      top: 100px;
      left: 100px;
      height: 75px;
      width: 200px;
      position: absolute;
      border: solid 1px black;
      border-width: 1px 3px;
      transform-origin: left center;  
      transform: scaleX(0.5) rotate(45deg) scaleY(2.667);
    }
    <div class="diamond"></div>

    It doesn't matter what the height and width of the element actually are as long as the scale factor is set correctly (such that they become equal). This factor can be calculated easily as the element has a set width and height. No other complex rotation or skew angle calculations are needed.

    Note: Transforms always affect the borders of an element. Some borders tend to get thicker while some others become thinner depending on the transform that is applied and the axis in which it is applied. So, it is always better to do a trial and error and set the border-width as appropriate. There is no simple solution for this particular problem.