Search code examples
csscss-shapescss-transformsbox-shadow

Inner Shadow getting aliased when skewed


As shown in the pic, the inset shadow becomes aliased when I use

-webkit-transform: skew(10deg);

It occurs both on chrome and in firefox, is there an work-around?

Screen print:

screenshot of skewed block

    #BlockOutside {
	  background-color: #cfcfcf;
	  padding: 5px;
	  padding-left: 3px;
	  padding-right: 3px;
	  height: 25px;
	  width: 15px;
	  -webkit-transform: skew(10deg);
    }
    #BlockInside {
	  background-color: gray;
	  width: 100%;
	  height: 100%;
  	  -webkit-box-shadow: inset 0 0 5px black;
    }
<div id="BlockOutside">
  <div id="BlockInside"></div>
</div>


Solution

  • This is due to the transform that is getting applied on the parent element. There is no way to get rid of this completely but you can remove it to a significant extent by making the back-face hidden and also adding a translateZ(0) (like mentioned in Woodrow Barlow's comment). The extra transform will not cause any undesired effects because it is only translating by 0px.

    backface-visibility: hidden;
    transform: skew(10deg) translateZ(0); /* translateZ(0) was added */
    

    Note: The backface-visibility property does need browser prefixes. I have used prefix-free library in the snippet to avoid writing the prefixed versions.

    #BlockOutside {
      background-color: #cfcfcf;
      padding: 5px;
      padding-left: 3px;
      padding-right: 3px;
      height: 50px;
      width: 30px;
      transform: skew(10deg) translateZ(0);
      backface-visibility: hidden;
    }
    #BlockInside {
      background-color: gray;
      width: 100%;
      height: 100%;
      box-shadow: inset 0 0 5px black;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    
    <div id="BlockOutside">
      <div id="BlockInside"></div>
    </div>


    Additionally, you could add an invisible 1px border like in the below snippet and it evens out the jagged edges even more. Note that this does add a bit of a blur effect but the edges are less jagged than the above snippet. You could use or ignore this option based on your needs.

    #BlockOutside {
      background-color: #cfcfcf;
      padding: 4px 6px 6px 4px;
      height: 50px;
      width: 30px;
      transform-style: preserve3d;
      transform: skew(10deg) translateZ(0);
      backface-visibility: hidden;
      border: 1px solid transparent;
    }
    #BlockInside {
      background-color: gray;
      width: 100%;
      height: 100%;
      box-shadow: inset 0 0 5px black;
      border: 1px solid transparent;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    
    <div id="BlockOutside">
      <div id="BlockInside"></div>
    </div>