ホームページ > 記事 > ウェブフロントエンド > 今すぐ CSS プロパティ calc()_html/css_WEB-ITnose の使用を開始してください
4 年前、CSS3 クリック チャートの記事を読んだ後、私は calc() を初めて知りました。もちろん、基本的な数学演算 (加算、減算、乗算、除算) が CSS で適用できることを知ってとてもうれしく思いました。
ほとんどの人は、前処理によって論理演算を実現できると考えているかもしれません。ただし、プリプロセッサは、角度単位、時間単位、周波数単位、解像度単位、固定長単位などの同じ単位でのみ動作できます。また、calc() は、混合単位を使用した論理演算を実装できます。
1turn は常に 360deg、100grad は常に 90deg、3.14rad は常に 180deg です。 1s は常に 1000 ミリ秒、1kHz は常に 1000Hz、1 インチは常に 2.54 cm または 25.4 mm または 96px、1dppx は常に 96DPI に等しくなります。これが、プリプロセッサがそれらの間で変換を行い、混合操作を実行できる理由です。ただし、コンテキストが欠如しているため、プリプロセッサは 1em または 1% または 1vmin または 1ch のピクセル数を処理できません。
まず簡単な例を見てみましょう:
div { font-size: calc(3em + 5px); padding: calc(1vmax + -1vmin); transform: rotate(calc(1turn - 32deg)); background: hsl(180, calc(2*25%), 65%); line-height: calc(8/3); width: calc(23vmin - 2*3rem);}
場合によっては、calc() 関数で変数を渡す必要があるかもしれません。これは、主流のプリプロセッサで実現できます。
まず、Sass を使用して、他のネイティブ CSS 関数と同じように変数を挿入します:
$a: 4emheight: calc(#{$a} + 7px)
LESS は次のように記述されます:
@a: 4em;height: ~"calc(@{a} + 7px)";
そして Stylus:
a = 4emheight: "calc(%s + 7px)" % a
ネイティブ CSS 変数も使用できますが、注意してください。 、Firefox 31 以降でのみサポートされており、他のブラウザは CSS 変数をまだサポートしていません。
--a: 4em;height: calc(var(--a) + 7px);
calc() 関数を正常に動作させるためには、次の点に注意する必要があります。まず、ゼロで割るのは明らかに機能しません。関数名と括弧の間にはスペースを入れてはいけません。プラス演算子とマイナス演算子はスペースで区切る必要があります。
以下は、いくつかの間違った書き方です:
calc(50% / 0)calc (1em + 7px)calc(2rem+2vmin)calc(2vw-2vh)
calc() 関数のパラメータは、指定された単位の有無にかかわらず数値である必要があり、どちらも受け入れられます。基本的なサポートは非常に充実していますが、それでもいくつかのトラブルに遭遇する可能性があります。いくつかの例を見て、どのような互換性の問題があるのか、そしてこれが最善の解決策であるかどうかを見てみましょう。
虹のグラデーションを実装します。リンク例:
background: linear-gradient(#f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
ただし、これらの 16 進値は理解するのが簡単ではありません。 HSL() と calc() を使用すると、より明確になります。仕事してないよ。つまり、デモは WebKit ブラウザーでのみ実行されます。したがって、実際には、この時点では、プリプロセッサに操作を実行させる方がよいでしょう。前処理を使用するもう 1 つの利点は、ループしてリストを生成することです。
background: linear-gradient(hsl(calc(0*60), 100%, 50%), hsl(calc(1*60), 100%, 50%), hsl(calc(2*60), 100%, 50%), hsl(calc(3*60), 100%, 50%), hsl(calc(4*60), 100%, 50%), hsl(calc(5*60), 100%, 50%), hsl(calc(6*60), 100%, 50%));
弾性要素にグラデーションの背景色を追加します
$n: 6;$l: ();@for $i from 0 through $n { $l: append($l, hsl($i*360/$n, 100%, 50%), comma);}background: linear-gradient($l);
ただし、calc() を使用する場合、必要なグラデーションは 1 つだけです:
background: linear-gradient(#e53b2c 1em, transparent 1em), linear-gradient(0deg, #e53b2c 1em, #f9f9f9 1em);
この書き込み方法は、calc() と gradients をサポートするすべてのブラウザで機能します。関係するユニットが含まれるため、プリプロセッサの論理演算と同等ではありません。さらに、変数を定義することで保守を容易にすることができます:
background: linear-gradient(#e53b2c 1em, #f9f9f9 1em, #f9f9f9 calc(100% - 1em), #e53b2c calc(100% - 1em));
注: 何らかの理由で、Chrome と Opera では、一方のストライプが他方よりもわずかにぼやけて細くなります。
斜めストライプのグラデーション
$s: 1em;$c: #e53b2c;$bg: #f9f9f9;background: linear-gradient($c $s, $bg $s, $bg calc(100% - #{$s}), $c calc(100% - #{$s}));
この場合、ストライプの幅は要素自体のサイズに依存します。場合によっては、これだけが必要な場合もあります。たとえば、CSS を使用してフラグを実装したい場合です。旗に緑、黄、青のグラデーションを少し加えます。旗愛好家ならそれがタンザニアの国旗であると認識できるでしょう。
background: linear-gradient(to right bottom, transparent 42%, #000 0, #000 58%, transparent 0);
タンザニアの国旗 (拡大画像を表示)
しかし、斜めのストライプを要素のサイズに依存せず、固定幅にしたい場合はどうすればよいでしょうか?次に、calc() を使用する必要があります。開始点では、固定ストリップの幅は 50% プラス半分、終了点では、50% から固定ストリップの幅の半分です。ストライプの幅を 4em にしたい場合は、次のように記述します:
background: linear-gradient(to right bottom, #1eb53a 38%, #fcd116 0, #fcd116 42%, #000 0, #000 58%, #fcd116 0, #fcd116 62%, #00a3dd 0);
このデモをテストするには、ウィンドウのサイズを変更できます。要素のサイズはビューポートのサイズによって設定されますが、ビューポートが変化しても、斜めのストライプは常に同じ幅のままです。
子要素を既知のサイズ内に配置する
background: linear-gradient(to right bottom, transparent calc(50% - 2em), #000 0, #000 calc(50% + 2em), transparent 0);
calc() を使用すると、マージンを取り除くことができます:
position: absolute;top: 50%; left: 50%;margin: -2em -2.5em;width: 5em; height: 4em;
次のこともできます:変数を使用して幅と高さを定義します:
position: absolute;top: calc(50% - 2em); left: calc(50% - 2.5em);width: 5em; height: 4em;
オフセット (上から、左から) を使用した最初の位置決めは問題ありませんが、後で要素の位置を移動する予定がある場合は、変換を使用する必要があることに注意することが重要です。これは、トランジションの変更には合成のみが必要ですが、オフセットの変更には再レイアウトが必要になり、再描画がトリガーされるため、パフォーマンスに影響を与えるためです。
由于position有四个属性值,我一直没热衷使用过calc()来定位相对于元素的右侧或底部的背景。但是,calc()是背景相对的某个定位的元素中间的绝佳解决方案。
几年前,我发现自己想在一个起点固定的网格上创建一个表示坐标的背景。
网格坐标系统(查看大版)
该网格部分很容易实现:
background-image: linear-gradient(#e53b2c .5em, transparent .5em) /* horizontal axis */, linear-gradient(90deg, #e53b2c .5em, transparent .5em) /* vertical axis */, linear-gradient(#333 .25em, transparent .25em) /* major horizontal gridline */, linear-gradient(90deg, #333 .25em, transparent .25em) /* major vertical gridline */, linear-gradient(#777 .125em, transparent .125em) /* minor horizontal gridline */, linear-gradient(90deg, #777 .125em, transparent .125em) /* minor vertical gridline */;background-size: 100vw 100vh, 100vw 100vh, 10em 10em, 10em 10em, 1em 1em, 1em 1em;
但是,但是我们怎样把起点放到中间,而不是在左上角?
首先,background-position: 50% 50%这个写法是不正确的,它会在相对于元素50% 50%这个点的基础上再定位出 50% 50%的渐变点,而且top和left两个方向的渐变线是分开计算的。这个问题的解决方法是,使用 calc() 来重新定位这些渐变,目的是使这些渐变尽量的相对于在整个viewport的中心位置,之后只要再向上和左两个方向位移坐标轴的一半或者栅格线的一半宽度即可。
background-position: 0 calc(50vh - .25em), calc(50vw - .25em), 0 calc(50vh - .125em), calc(50vw - .125em), 0 calc(50vh - .0625em), calc(50vw - .0625em);
同样,我们可以通过使用变量使其更易于维护:
演示链接 system of coordinates + grid #2 by Ana Tudor (@thebabydino) on CodePen.
在构建HTML幻灯片的时候,我总是希望在一个窗口下,沿着某一个轴的中心拖拽,图片能有固定的比例。
比例箱动画
我们假设幻灯片的大小比例为 4:3,我是一个宽屏显示器上演示。幻灯片要想覆盖视口,左,右肯定会有一些留白。
比例盒:情况1(查看大版)
视觉高度为100vh。已知的高度,宽高比,可以得到宽度,公式为4/3 * 100vh。我们想要让他在中间的话,需要从偏移一半视口的宽度(100vw / 2),再减去幻灯片的宽度的一半(4/3 * 100vh / 2)。这时我们就需要的calc(),因为我们有混合单位。
.slide { position: absolute; left: calc(100vw/2 - 4/3*100vh/2); width: calc(4/3*100vh); height: 100vh;}
然而,当我们的窗口小于4:3的时候。在这种情况下,幻灯片盖住了水平方向的窗口,在顶部和底部留有一定的空间。
比例盒:情况2(查看大版)
覆盖了视水平意味着宽度为100vw。根据宽高比,我们可以得出高度为 3/4*100vw。最后,顶部偏移量和刚刚的算法一样,也就是 100vh/2 - 3/4*100vw/2。
@media (max-aspect-ratio: 4/3) { .slide { top: calc(100vh/2 - 3/4*100vw/2); left: auto; /* Undo style set outside media query */ width: 100vw; height: calc(3/4*100vh); }}
当然,我们还可以用变量来定义宽高比例。这里有一个在线的demo,可以通过调整窗口大小来测试。
$a: 4;$b: 3;.slide { position: absolute; top: 0; left: calc(50vw - #{$a/$b/2*100vh}); width: $a/$b*100vh; height: 100vh; @media (max-aspect-ratio: #{$a}/#{$b}) { top: calc(50vh - #{$b/$a/2*100vw}); left: 0; width: 100vw; height: $b/$a*100vw; }}
另外,我们还可以使用比全局变量更好的方式,使用mixin实现:
@mixin proportional-box($a: 1, $b: $a) { position: absolute; top: 0; left: calc(50vw - #{$a/$b/2*100vh}); width: $a/$b*100vh; height: 100vh; @media (max-aspect-ratio: #{$a}/#{$b}) { top: calc(50vh - #{$b/$a/2*100vw}); left: 0; width: 100vw; height: $b/$a*100vw; }}.slide { @include proportional-box(4, 3);}
注意,变量 $a 和 $b 必须是整数,才能正常的实现媒体查询。
以上在主流浏览器目前所有版本的支持。然而,直到最近, WebKit浏览器都不支持在calc()函数中使用视口单位,不过,这个问题已被分别在Safari 8和Chrome 34,Opera浏览器中修复。
关于幻灯片演示,我有两件事要说。
首先是为幻灯片没有真正覆盖整个视口的边缘,因为可能会被切断。这是一个容易解决。我简单地设置他们箱尺寸为边界盒上他们还设置了边界。
第一件事是,幻灯片并没有真正的覆盖窗口边缘,因为可能会被切断掉边框。这个很容易解决。只需要设置 box-sizing 为 border-box就可以了。
第二件事是给空白的幻灯片上添加一行文字,来标识。
期望的结果(查看大版)
我不想使用绝对定位,所以我想我会用设置了合适的line-height。
如果幻灯片的高度包含边框,覆盖了窗口的整个高度,那么行高就是 100vh减去两个边框宽度:
$slide-border-width: 5vmin;.slide { /* The other styles */ box-sizing: border-box; border: solid $slide-border-width dimgrey; h1 { line-height: calc(100vh - #{2*$slide-border-width}); }}
在这种情况下,包括边界,相对于窗口水平垂直居中,那么它的高度就是$b/$a*100vw。那么,标题的line-height 将是减去幻灯片的边框宽度的两倍:
line-height: calc(#{$b/$a*100vw} - #{2*$slide-border-width});
这是我最初的想法,理论上,应该是可行的。它确实在WebKit浏览器和IE可以。但事实证明,在Firefox里,,calc()值下,行高和其他一些属性不起作用。这个问题已解决。这样的话, calc() 就不是最佳的解决方案。幸运的是,还有很多其他的方法来解决这个问题(Flexbox的,绝对定位等等)。
有件事情,我特别热衷,那就是CSS 3D -尤其是使用CSS创建几何3D形状。如果我创建一个形状,通常会放到窗口的中间位置。
我会设置元素的 perspective, 还有这个图形的父级元素。这个是透视图,这里我们不做详细介绍。 如果您想了解更多关于他们是如何定位的,可以看我的CSS-技巧博客文章。
设置一个 perspective,是为了确保我们看到的一切,越近物体越大,越远物体越小。这个属性perspective接受长度值,值越小,对比度越大,离我们更近,反之,渐远同理。
现在,我们来说一个非常简单的3D形状 - 一个立方体,例如 - 就在我们屏幕的中央。它看起来并不十分3D:这是太对称,正面是完全不透明的,我们只能看到最前面的面。
立方体(查看大版)
我们可以将其旋转一点,旋转30度吧,围绕其y轴线(即穿过立方体中间的垂直轴)或围绕其点x轴线。这样看起来更好,但我们只能看到两个面。此外,我们看到物体旋转了,但这不是我们的目的。
旋转立方体(查看大版)
还有件事,我们可以做调整的就是视觉点。这个属性叫perspective-origin。它的默认值是50% 50% 。这是相对于场景,我们知道,50% 50%的视觉点会将形状定位到中心点。现在,我们希望这个向上和向右。那么只需要设置perspective-origin: 100% 0就可以了。但这里有一个问题:我们看到的立方体展示效果将取决于窗口的尺寸(你可以测试这个通过调整视口)。
改变的窗口大小,我们看到的立方体效果。
perspective-origin定义为 100% 0,是从右上角看过去,但立方体是总是都在场景的中部。因为这个原因,改变窗口的尺寸将改变为 50% 50%(立方体被定位的位置),和 100% 0(我们设置的视角起点)之间。
可以使用calc()来设置perspective-origin,从默认值的50%加上或者减去一个固定值。
perspective-origin: calc(50% + 15em) calc(50% - 10em);
解决方案
您可以通过调整视口测试。
你已经使用calc() 了?如果是的话,那么你用在了什么情况下?