『CSS Secrets』は @Lea Verou による最新の本で、CSS に関する小さな秘密がいくつか説明されています。これは CSSers にとって読む価値のある本です。一定期間読んだ後、私、@全域と @彦子は、関連する読書感想文を W3cplus で公開し、皆さんと共有します。
要素の 1 つの角にスタイルを追加して、さまざまな程度で折り畳まれているように見せます (通常は右上隅または左下隅)リアルなエフェクトは、近年非常に人気のあるエフェクトです。
最近、純粋な CSS ソリューションがいくつかあり、その最初のソリューションは 2010 年に疑似要素の第一人者である Nicolas Gallagher によってリリースされました。これらは通常、左上隅に 2 つの三角形を追加することによって作成されます。1 つはページをめくるため、もう 1 つはメイン要素の角をぼかします。これらの三角形は通常、古い境界線のトリックを使用して作成されます。
注: csstricks.com のドッグイヤー効果のいくつかの初期デザインは、各記事の右上隅に表示されます。
これらのソリューションは、当時は印象的でしたが、現在では次のような状況で多くの制限や欠点があります:
CSS を直接使用して、より柔軟に作成する方法はありますか?このような状況でも失敗しない折りたたみコーナー効果はありますか?
まず、第 3 章、セクション 4 で説明した勾配ベースの解法に基づいて作成された、右上隅にベベルのある要素から始めます。この手法を使用して 1em の右上ベベルを作成するコードは次のとおりです:
background: #58a; /* Fallback */background:linear-gradient(-135deg, transparent 2em, #58a 0);
効果は次のとおりです:
キャプション: 私たちの出発点:グラデーションで完成した、斜めの角を持つ右上隅の要素
この時点で、すでに半分が完了しています。必要なのは、ページめくり効果用の暗い三角形を追加することだけです。別のグラデーションを追加して三角形を作成する必要があるため、必要に応じて、background-size の値と右上隅の位置を再調整します。
三角形を作成するには、斜めの線形グラデーションを作成する必要があります:
background:linear-gradient(to left bottom,transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em;
キャプション: 三角形を折りたたむために完成した 2 番目のグラデーションです。のテキストは白ではなく明るいグレーで表示されているため、テキストがどこにあるかがおおまかにわかります
上の図では、このグラデーションの背景だけの効果がわかります。最後のステップはそれらを結合することです。これを実行します。試してみて、三角形のフリップがノッチ グラデーションの上にあることを確認してみましょう。
background: #58a; /* Fallback */background: linear-gradient(to left bottom,transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-135deg, transparent 2em, #58a 0);
下の画像からわかるように、結果は期待したものではありません。なぜサイズが合わないのでしょうか?それらはすべて 2em です!
注: 2 つのグラデーションを組み合わせても、期待した結果が得られませんでした。
その理由は、(第 3 章の 4 番目のセクションで説明したように) 2em ベベルです。 2 番目のグラデーションの寸法はカラー ノードで、そこからベベルの方向にグラデーション ラインに沿って測定されます。一方、background-size の 2em の長さは、水平方向と垂直方向に測定された背景タイルの幅と高さです。
2 つの次元を揃えるには、2 つの次元のどちらを保持したいかに応じて、次のいずれかを実行できます。
背景サイズは 2 回繰り返され、他のほとんどの CSS サイズは対角線で測定されないため、通常は水平方向に 2em を残すことをお勧めします。このようにして、カラー ノードの位置は 2 を 2 の平方根で割った値となり、ほぼ 1.414213562 に等しくなります。つまり、最終的には 1.5em になります。
background: #58a; /* Fallback */background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-135deg, transparent 1.5em, #58a 0);
以下に示すように、柔軟でシンプルな丸い角が完成します。
キャプション: 青のグラデーション カラー ノードの位置を変更した後、折り畳まれたコーナーがついに完成しました
少なくとも十分なパディングがあることを確認してください折り畳まれた角のサイズより大きくなければ、テキストが角を覆い(単なる背景であるため)、折り畳まれた角の視覚効果が損なわれます。
実際の折り畳み角度がちょうど 45° になることはほとんどありません。もう少し現実的にしたい場合は、-150 度など、わずかに異なる角度を使用して 30 度の角度を完成させることができます。ただし、ベベルの角度のみを変更すると、ページめくり効果を表す三角形が自動的に調整されず、図に示すように 2 つの角が分割されてしまいます。
キャプション: 切開角度を変更すると剥離が生じる可能性があります
但是,我们不能直接调整它的尺寸。三角形的大小不是通过角度定义的,而是通过它的 width 和 height 值确定的。那我们要怎样才能找到我们需要的 width 和 height 值呢?Well,三角函数的知识是时候派上用场了!
目前的代码是长这样的:
background: #58a; /* Fallback */background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 2em 2em, linear-gradient(-150deg, transparent 1.5em, #58a 0);
你可以在下图中看到,如果我们需要计算两个 30-60-90 直角三角形斜边的长度,我们需要知道它们其中一条边的长度。
图注:我们的切角,放大(灰色标记的角为 30° )
下图所示的极坐标中的三角函数提醒我们,如果我们知道角度和三角形一条边的长度,我们可以通过使用正弦、余弦、和勾股定理计算它的另外两条边的长度。
图注:正弦和余弦根据一个角和斜边,帮我们计算出了直角三角形的边长
通过数学知识(或计算器),我们知道 cos 30° 等于根号三除以 2 和 sin 30° 等于二分之一。我们还知道,在我们的示例中,根据三角函数, sin 30° = 1.5 / x 以及 cos 30° = 1.5 / y ,因此:
在这里,根据勾股定理,我们可以计算出 z 的值:
现在我们可以调整三角形的大小了:
background: #58a; /* Fallback */background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) no-repeat 100% 0 / 3em 1.73em, linear-gradient(-150deg, transparent 1.5em, #58a 0);
现在,我们的折叠角如图所示。
图注:尽管我们确实达到了我们想要的结果,事实却证明,它看起来非常不真实
你可以看到,现在的三角形虽然和我们的切口相匹配,但是效果看起来并不逼真!虽然我们可能还不能很快找出原因,我们前面已经看到过很多折叠角了,所以我们一眼就能看出它和我们的视觉习惯严重偏离了。你可以通过给一个实际的纸片折一个这样角度的角,来帮助弄明白为什么这个效果看起来这么假。在纸上我们找不出能够折叠出隐约如上图这样效果的角的方法。
你可以拿张纸折一个角看看,如图所示
图注:模拟折叠角效果(Leonie and Phoebe Verou的可爱纸片)
我们想要的三角形是稍微旋转的,并且和我们“剪”掉的三角形的尺寸是一样的。因为我们不能旋转背景,所以是时候用伪元素来移动效果了:
.note { position: relative; background: #58a; /* Fallback */ background: linear-gradient(-150deg, transparent 1.5em, #58a 0);}.note::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) 100% 0 no-repeat; width: 3em; height: 1.73em;}
这里,我们复制了刚刚下图中的效果,放到伪元素中。
我们的下一步是通过交换其 width 和 height 来让它变成我们切掉的角的对称角,改变三角形的方向,而不是互补。然后我们将其按照 30° ( (90° – 30°) – 30° ) 的方向逆时针旋转。使其斜边平行于我们的切口角:
.note::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.4) 0) 100% 0 no-repeat; width: 1.73em; height: 3em; transform: rotate(-30deg);}
你可以在下图中看到我们改变后的效果。
图注:我们差不多完成了,但是我们需要移动三角形
正如你看到的,我们现在只需要移动三角形,使我们的两个三角形(黑色的和切开的那个)的斜边重合。就目前看,我们需要在水平和垂直方向移动三角形,所以比较难确定要怎么移动。我们可以通过把 transform-origin 设置为 bottom right ,让事情变得简单一点,这样三角形的右下角就会变成旋转中心,然后,保持固定在同一个地方:
.note::before { /* [Rest of styling] */ transform: rotate(-30deg); transform-origin: bottom right;}
确保把 translateY() 变换放在旋转之前,否则我们的三角形将沿它的 30° 角移动,因为每个变换都将让元素的整个坐标系统一起变换,而不仅仅是元素本身!
如下图所示:
图注:添加 transform-origin: bottom right; 可以让事情变得简单很多:现在我们只需要在垂直方向移动我们的三角形就ok了。
现在我们只需要向上垂直移动我们的三角形。为了找到确切的值,我们可以再次使用几何来解决问题。如下图所示
图注:知道我们的三角形要移动多少并不像看起来那么难
我们的三角形需要的垂直偏移量是 x-y=3-(根号三) 1.267949192 ,结果约为 1.3em :
.note::before { /* [Rest of styling] */ transform: translateY(-1.3em) rotate(-30deg); transform-origin: bottom right;}
下图中的效果,终于给了我们想要的效果。
图注:我们的三角形终于对上了~~好感动有木有
呼~真是不容易!此外,现在我们的三角形是通过伪元素生成的,我们可以让它变得更加逼真,通过添加圆角,(实际的)渐变,还有 box-shadow s!最后的代码如下所示:
.note { position: relative; background: #58a; /* Fallback */ background: linear-gradient(-150deg, transparent 1.5em, #58a 0); border-radius: .5em;}.note::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.2) 0, rgba(0,0,0,.4)) 100% 0 no-repeat; width: 1.73em; height: 3em; transform: translateY(-1.3em) rotate(-30deg); transform-origin: bottom right; border-bottom-left-radius: inherit; box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.15);}
你可以在下图中欣赏我们的劳动成果。
效果看起来不错,但是代码重用的情况如何呢?我们来想一些常见的修改和变化:
最后两个是比较难的。可能需要使用预处理器的 @mixin :
@mixin folded-corner($background, $size,$angle: 30deg){ position: relative; background: $background; /* Fallback */ background: linear-gradient($angle - 180deg, transparent $size, $background 0); border-radius: .5em; $x: $size / sin($angle); $y: $size / cos($angle); &::before { content: ''; position: absolute; top: 0; right: 0; background: linear-gradient(to left bottom, transparent 50%, rgba(0,0,0,.2) 0, rgba(0,0,0,.4)) 100% 0 no-repeat; width: $y; height: $x; transform: translateY($y - $x) rotate(2*$angle - 90deg); transform-origin: bottom right; border-bottom-left-radius: inherit; box-shadow: -.2em .2em .3em -.1em rgba(0,0,0,.2); }}/* used as... */.note { @include folded-corner(#58a, 2em, 40deg);}
注意:在本书写作期间,SCSS还没有原生支持三角函数。要启用支持,你可以使用 Compass框架 ,相对于其它库。你甚至可以自己写,使用泰勒展开函数!LESS,同样可以调用它们。