Chinese Window Lattice And CSS

本文围绕用CSS绘制中国窗棂展开。介绍了CSS的反射属性,虽非标准但很优雅。阐述了该属性的四个反射方向,探讨了添加多个反射的方法。以窗棂为例,从确定种子元素、添加反射到持续展开,用少量代码实现绘制,不过该方法仅在Chrome和Safari中可用。
谁向云端着此亭,檐前树木映窗棂。
-- 释绍嵩《陪赵知府登桃岭山亭》

风过窗棂(image from 中国窗棂)

The traditional Chinese window lattice has a symmetrical beauty, as well as a very beautiful formal name -- 窗棂.

As a CSS lover, I've always wanted to draw them with CSS by hand. But that's never being easy. I thought using SVG might be much straightforward until I learned how to apply the -webkit-box-reflect property.

The property

Unfortunately, -webkit-box-reflect is non-standard. The standard way is to use element() function, which has been implemented in Firefox already.

Honestly the -webkit-box-reflect property seems much elegant to me because it has a better name and it doesn't rely on an extra id like element()does. I don't get why it wasn't accepted by the CSS WG.

There's also an article in detail about reflection in CSS along with several demos by Ana Tudor back from 2016.

Directions

The -webkit-box-reflect property provides four directions of reflection:abovebelowleft and right. This is how to use it:

.box {
  -webkit-box-reflect: above|below|left|right; }

Perhaps because it's just an experimental property from the very beginning, there's no way yet to add multiple reflections to an element at once.

-webkit-box-reflect directions

I think it would be much cooler to have multiple reflections and reflections in various degrees other than only 4 of them.

It's still exciting

Let's start with a single div element and its reflection on the right side.

<div>△</div>

<style>
  div { -webkit-box-reflect: right; } </div>

reflection on the right side

How to add another reflection?

Not long ago Chris Coyier introduced a trick in this article, about how to add shadows to a clipped element by applying drop-shadow to its parent node.

Yes, we can do something similar by adding a parent node and setting reflection to it.

<div class="parent">
  <div class="box">△</div> </div> <style> .box { -webkit-box-reflect: right; } .parent { -webkit-box-reflect: below; } </style>

reflection on the parent node

It's like unfolding a sheet of paper, first in half from left to right and then top to bottom. However, the order doesn't really matter.

 

Although it's not the exact result we wanted, it's so exciting to find a way to add multiple reflections.

Going deep

The total number of elements grows exponentially in this way, which is dependent on the depth of the nested divs.

So given 2 nested divs like the above, there will be 2^2 = 4 elements (including all the reflections). Given 7 of them will be 2^7 = 128 elements.

relecions on deep nested divs

Seed

The innermost div can be treated as a seed. Since the whole graph composed with reflections will change with it.

For example, rotate it with -45 degree:

...
  <div>
    <div>
      <div class="seed">△</div> </div> </div> ... <style> /* ... */ .seed { /* ... */ transform: rotate(-45deg); } </style>

reflection

Or combine with any other properties and some old methods. It seems another different way to build Unicode Patterns as well.

reflection

Chinese Window Lattice

So with the -webkit-box-reflect property and the technique described above, we can finally draw those symmetrical window lattices in CSS with very few lines of code.

I want to take the picture at the beginning of the article as an example. Let's see how to draw them step by step.

1. The seed element

First, find out the smallest part that can't be divided any further. Here we start from the part in the upper left corner as the seed element.

seed element frame

And then draw these lines with background linear-gradient. Using :emptyselector to target the seed element for simplicity.

<div></div>

<style>
  div:empty { width: 72px; height: 72px; --g: linear-gradient(#000, #000); --gs: linear-gradient(-45deg, transparent calc(50% - 1px), #000 calc(50% - 1px), #000 calc(50% + 1px), transparent calc(50% + 1px) ); background: var(--g) 0 0 / 100% 2px, var(--g) 100% 0 / 2px 48px, var(--g) 100% 48px / 24px 2px, var(--g) 48px 100% / 2px 24px, var(--g) 0 100% / 48px 2px, var(--g) 0 0 / 2px 100%, var(--g) 0 46px / 24px 2px, var(--g) 24px 100% / 2px 26px, var(--g) 100% 24px / 26px 2px, var(--g) 46px 0 / 2px 24px, var(--gs) 50% 50% / 24px 24px, var(--gs) 0 0 / 40px 40px; background-repeat: no-repeat; } </style>

2. Add reflection

The reflection begins with the seed element itself. We pick "right" as an initial direction and use custom property to make it more intuitive.

<div style="--reflect: right -3px"></div>

<style> div { -webkit-box-reflect: var(--reflect); } div:empty { /* ... */ } </style>

add reflection

3. Continue unfolding

So we're going to add parent nodes for more reflections. It really helps to understand if you think of it as unfolding a sheet of paper.

<div style="--reflect: below -2px"></div>
  <div style="--reflect: right -3px"></div> </div>

reflection like unfolding a piece of paper

Add another one.

<div style="--reflect: below calc(200% - 6px)"></div>
  <div style="--reflect: below -2px"></div> <div style="--reflect: right -3px"></div> </div> </div>

continue unfolding

Repeat the process until we get the desired result.

<div style="--reflect: right calc(600% - 14px)">
  <div style="--reflect: right calc(200% - 6px)"> <div style="--reflect: below calc(400% - 10px)"> <div style="--reflect: below calc(200% - 6px)"> <div style="--reflect: below -2px"> <div style="--reflect: right -2px"></div> </div> </div> </div> </div> </div>

Chinese window lattice

That's it.

You can see the result and the complete source code on CodePen. But you know it works only in Chrome and Safari.

Conclusion

The solution using -webkit-box-reflect property is beautiful in some way. I really wish it had been accepted as a standard and can even do reflections in various directions. So that it may be possible to do JianZhi (Chinese Paper-cutting Art) in CSS.

 

from:https://yuanchuan.dev/2019/05/15/window-lattice-and-css.html

转载于:https://www.cnblogs.com/makai/p/11041142.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值