简体   繁体   中英

CSS Filters break 3D transforms

I was experimenting with CSS transforms when I found that filters flatten the transforms, just like transform-style: flat .

 var toggleFilter = function() { var div = document.getElementById("cube") if (div.className == "cube") { div.className = "cube filter" } else { div.className = "cube" } }
 * { transform-style: preserve-3d } div.cube { height: 100px; width: 100px; background: blue; transform: rotateX(45deg) rotateZ(45deg); border: solid 2px black; box-sizing: border-box; } div.face1 { content: ""; height: 100px; width: 100px; background: green; transform: rotateY(90deg) translateZ(50px) translateX(50px); border: solid 2px black; box-sizing: border-box; } div.face2 { content: ""; height: 100px; width: 100px; background: red; transform: rotateY(90deg) rotateX(-90deg) translateZ(-50px) translateX(50px); border: solid 2px black; box-sizing: border-box; } div.perspective { perspective: 900px; position: absolute; margin: 50px; }.filter { filter: opacity(1); -webkit-filter: opacity(1); }
 <div class="perspective"> <div id="cube" class="cube"> <div class="face1"></div> <div class="face2"></div> </div> </div> <button onclick="toggleFilter()">Toggle.filter</button>

Here's a fiddle demonstrating this. I couldn't find any information on this anywhere, so I would like to know if there is a workaround for this.

As per W3C Transforms Spec :

The following CSS property values require the user agent to create a flattened representation of the descendant elements before they can be applied, and therefore override the behavior of transform-style: preserve-3d :

overflow : any value other than visible.

filter : any value other than none.

clip : any value other than auto.

clip-path : any value other than none.

isolation : used value of isolate.

mask-image : any value other than none.

mask-box-image-source : any value other than none.

mix-blend-mode : any value other than normal.

The computed value of transform-style is not affected.

This is the reason why the 3D transforms are broken and the layers are flattened when you toggle on the filters. The one workaround that I know for this situation is creating the entire cube using sibling elements and apply the filter on the sibling elements directly instead of applying on the parent.

 var toggleFilter = function() { var div = document.getElementById("cube") if (div.className == "cube") { div.className = "cube filter" } else { div.className = "cube" } }
 * { transform-style: preserve-3d } div.cube { position: relative; height: 100px; width: 100px; transform: rotateX(45deg) rotateZ(45deg); } div.face0 { position: absolute; content: ''; height: 100%; width: 100%; top: 0px; left: 0px; background: blue; border: solid 2px black; box-sizing: border-box; } div.face1 { content: ""; height: 100px; width: 100px; background: green; transform: rotateY(90deg) translateZ(50px) translateX(50px); border: solid 2px black; box-sizing: border-box; } div.face2 { content: ""; height: 100px; width: 100px; background: red; transform: rotateY(90deg) rotateX(-90deg) translateZ(-50px) translateX(50px); border: solid 2px black; box-sizing: border-box; } div.perspective { perspective: 900px; position: absolute; margin: 50px; }.filter.face0, .filter.face1, .filter.face2 { filter: opacity(25%); -webkit-filter: opacity(25%); }
 <div class="perspective"> <div id="cube" class="cube"> <div class="face0"></div> <div class="face1"></div> <div class="face2"></div> </div> </div> <button onclick="toggleFilter()">Toggle.Filter</button>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM