この記事は初期翻訳であり、校正されていません。参考まで。実際には、保守可能なコードの 1 つの大きな要素は、変更を加えるために必要な編集の量を最小限に抑えることです。たとえば、ボタンを拡大するには、さまざまなルールで 10 回の編集を行う必要があり、そのうちのいくつかを見逃す可能性があります。特に、元のコードを書いた人ではない場合は、たとえ編集が明らかだったとしても、あるいは後で見つけたとしても、もっと有効に活用できる時間を無駄にしていることになります
ソフトウェア開発では、コードをドライな状態に保ちます。保守性は最大の課題の 1 つであり、これは CSS にも当てはまります。実際には、コードの保守性における最大の要素は、図 1.4
例で使用するボタン
このボタンは例全体で使用されます。
図 1.4
に示すボタンのスタイルを設定する次の CSS を見てみましょう:
ボタンにいくつかの効果を追加する次の CSS を見てみましょう (
図 1.4を参照):
padding: 6px 16px;border: 1px solid #446d88;background: #58a linear-gradient(#77a0bb, #58a);border-radius: 4px;box-shadow: 0 1px 5px gray;color: white;text-shadow: 0 -1px 1px #335166;font-size: 20px;line-height: 30px;
このコードの保守性に関しては、簡単に修正できる問題がいくつかありますが、フォント サイズを変更することにした場合 (おそらく、重要な大きなボタンに使用されるバリエーションを作成するため) です。 )、行間隔は両方とも絶対値であるため、行間隔も調整する必要があります。さらに、行間隔はフォント サイズとの関係を反映していないため、行間隔をどのように設定すべきかを把握するために計算を実行する必要さえあります。値が互いに依存している場合、この場合、行間隔は行の高さの 150% になるため、これを表示する方がはるかに保守しやすくなります。コード内:
このコードには保守性の問題がいくつかあります。それらを 1 つずつ修正していきましょう。最も難しい部分は、おそらくフォント サイズに関連する部分です。フォント サイズを変更することにした場合、{1 [翻訳注: 本書では、「フォント サイズ」はフォント サイズ (font-size) の通称です。 ]} (おそらく、より大きくて重要なボタンを生成するため) の場合、両方の属性が絶対値として書き込まれるため、行の高さを同時に調整する必要があります。さらに厄介なことに、行の高さはフォント サイズとの関係を反映していないため、フォント サイズを変更した後に行の高さがどのようになるかを計算する必要があります。 特定の値が相互に依存する場合、その相互関係をコードで表現する必要があります。この例では、行の高さはフォント サイズの 1.5 倍です。したがって、コードを次のように変更すると、保守が大幅に簡単になります:
font-size: 20px;line-height: 1.5;
フォント サイズを拡大すると、絶対値を使用して指定されているため、ボタンの他の効果 (角の丸みが最も目立ちます) が無効になります。長さ
フォントを拡大するだけでは、ボタンの他の効果 (最も目立ちにくいのは丸い角) が破壊されます。これは、ボタンの他の効果には絶対的な長さの値が割り当てられているためです。
ここで、なぜフォント サイズを絶対長として指定したのでしょうか? 確かに、絶対長は扱いやすいですが、変更を加えるたびに厄介な問題が発生します。親フォント サイズを大きくする場合は、フォントの絶対値を使用するスタイルシートのルールをすべて変更する必要があります。パーセンテージまたは em を使用する方がはるかに優れています。
既然跨出了这一步,我们为什么还把字号定为绝对长度值呢?没错,绝对值很容易掌控,但每当你想要修改它们的时候,它们都会回头反咬你一口。比如说,如果我们决定把父级的字号加大时,我们将不得不修改每一处使用绝对值作为字体尺寸的样式。如果改用百分比或 em 单位就好多了:
/* Assuming a 16px parent font size */font-size: 125%; /* 假设父级的字号是 16px */line-height: 1.5;
Now if I change the parent font size, the button will instantly become bigger. However, it will look quite different ( Figure 1.5 ), because all other effects were designed for a smaller button and did not scale. We can make all the other effects scalable as well, by specifying any lengths in em s, so that they all depend on the font size. This way, we can control the size of the button in one place:
现在,如果我们改变父级的字号,按钮的尺寸就会随之变化。但是,它看起来很不协调( 图 1.5 ),因为所有其他效果都是为一个小按钮设计的,并没有跟着缩放。如果我们把这些长度值都改成 em 单位,那这些效果的值就都变成可缩放的了,而且是依赖字号进行缩放。按照这种方法,我们就可以在一处控制按钮的所有尺寸样式了:
padding: .3em .8em;border: 1px solid #446d88;background: #58a linear-gradient(#77a0bb, #58a);border-radius: .2em;box-shadow: 0 .05em .25em gray;color: white;text-shadow: 0 -.05em .05em #335166;font-size: 125%;line-height: 1.5;
{原书注释!}
Here we wanted our font size and measurements to be relative to the parent font size, so we used em s. In some cases, you want them to be relative to the root font size (i.e., the font size of ), and em s result in complex calculations. In that case, you can use the rem unit. Relativity is an important feature in CSS, but you do have to think about what things should be relative to .
这里我们希望字号和其他尺寸能够跟父级的字号建立关联,因此我们采用了 em 单位。但在某些情况下,你可能希望这些尺寸是和 根级字号 (即 元素的字号)相关联的,此时使用 em 可能会导致复杂的计算。在这种情况下,你可以使用 rem 单位。在 CSS 中,相关性是一个很重要的特性,但你得 想清楚 到底哪些东西是 真正相关 的。
Now our larger button looks much more like a scaled version of the original ( Figure 1.6 ). Notice that we still left some lengths as absolute values. It’s a judgment call which effects should scale with the button and which ones should stay the same. In this case, we wanted our border thickness to stay 1px regardless of the button dimensions.
现在我们的大号按钮看起来更像是一个原按钮的等比例放大版本了( 图 1.6 )。请注意仍然还有一些长度值是绝对值。 此时就需要重新审视到底哪些效果应该跟着按钮一起放大,而哪些效果的尺寸是保持不变的 。比如在这个例子中,我们希望按钮的边框粗细保持在 1px ,不受按钮尺寸的影响。
图 1.6
Now we can make our button larger, and all its effects scale too
现在我们可以把按钮放大,而且它的所有效果也都跟着放大了。
However, making the button smaller or larger is not the only thing we might want to change. Colors are another big one. For example, what if we want to create a red Cancel button, or a green OK button? Currently, we would need to override four declarations ( border-color , background , box-shadow , text-shadow ), not to mention the hassle of recalculating all the different darker/lighter variants of our main color, #58a , and figuring out how much lighter or darker each color is. Also, what if we want to place our button on a non-white background? Using gray for its shadow will only look as intended on a white background.
不过,让按钮变大或变小并不是我们唯一想要改动的地方。颜色是另一个重要的变数。比如说,假设我们要创建一个红色的取消按钮,或者一个绿色的确定按钮,该怎么做呢?眼下,我们可能需要覆盖四条声明( border-color 、 background 、 box-shadow 和 text-shadow ),更别提另一大难题了——我们还得根据按钮的亮面和暗面相对于主色调 #58a 变亮和变暗的程度来分别推导出其他颜色各自的亮色和暗色版本。此外,假设我们想把按钮放在一个非白色的背景之上呢?显然使用灰色( gray )作投影只适用于纯白背景的情况。
We could easily eliminate this hassle by using semi-transparent white and black for lighter/darker variants, respectively, overlaid on our main color:
其实只要把半透明的黑色或白色叠加在主色调上,即可产生出主色调的亮色和暗色变体,这样就能简单地化解这个难题了:
padding: .3em .8em;border: 1px solid rgba(0,0,0,.1);background: #58a linear-gradient(hsla(0,0%,100%,.2), transparent);border-radius: .2em;box-shadow: 0 .05em .25em rgba(0,0,0,.5);color: white;text-shadow: 0 -.05em .05em rgba(0,0,0,.5);font-size: 125%;line-height: 1.5;
{小提示}
[TIP] Use HSLA instead of RGBA for semi-transparent white, as it has slightly fewer characters and is quicker to type, due to the lack of repetition.
推荐使用 HSLA 而不是 RGBA 来产生半透明的白色,因为它的字符长度更短,打起来也更快。这归功于它的重复度更低。
Now all it takes to create variations with different colors is to override background-color ( Figure 1.7 ):
现在我们只要覆盖 background-color 属性,就可以得到不同颜色版本的按钮了(参见 图 1.7 ):
button.cancel { background-color: #c00;}button.ok { background-color: #6b0;}
图 1.7
All it took to create these color variations was changing the background color
只要改变背景色,就可以得到其他颜色版本的按钮了。
Our button is already much more flexible. However, this example doesn’t demonstrate every opportunity to make your code more DRY. You will find a few more tips in the following sections.
我们的按钮现在已经非常灵活了。不过,这个例子并没有涵盖所有能让代码变得更 DRY 的方法。你会在下面几节中发现更多的技巧。
Sometimes, maintainability and brevity can be mutually exclusive . Even in the previous example, our final code is a bit longer than our original. Consider the following snippet to create a 10px thick border on every side of an element, except the left one :
有时候, “代码易维护” 和 “代码量少” 不可兼得 。比如在上面的例子中,我们最终采用的代码甚至比一开始的版本还要略长一些。来看看下面的代码片断,我们要为一个元素添加一道 10px 宽的边框, 但左侧不加边框 。
border-width: 10px 10px 10px 0;
It’s only one declaration, but to change the border thickness we would need to make three edits. It would be much easier to edit as two declarations, and it’s arguably easier to read that way too:
只要这一条声明就可以搞定了,但如果日后要改动边框的宽度,你需要同时改三下。但如果把你它拆成两条声明的话,改起来就容易多了,而且它的可读性或许也会更好一些:
border-width: 10px;border-left-width: 0;
In CSS Color Level 3 , we got many new color keywords like lightgoldenrodyellow , which aren’t that useful. However, we also got a special new color keyword, borrowed from SVG: currentColor . This does not correspond to a static color value. Instead, it always resolves to the value of the color property, effectively making it the first ever variable in CSS . A very limited variable, but a variable nevertheless.
在 CSS 颜色(第三版) 规范中,增加了很多新的颜色关键字,比如 lightgoldenrodyellow 等,其实并不是很常用。但是,我们还得到了一个特殊的颜色关键字 currentColor ,它是从 SVG 那里借鉴来的。这个关键字并没有绑定到一个固定的颜色值,而是总是解析为 color 属性的值——实际上,这的特性让它成为 CSS 中有史以来的第一个变量 。虽然功能很有限,但它真的是个变量。
{原书注释!}
Some would argue that the em unit was actually the first variable in CSS, as it referred to the value of font-size . Most percentages play a similar role, though in less exciting ways.
可能有人会争论说 em 单位才是 CSS 中的第一个变量,因为它引用了 font-size 的值。其实大多数百分比数值也扮演了类似的角色,只不过它们的工作方式不是很起眼。
For example, let's assume we want all of the horizontal separators (all
举个例子,假设我们想让所有的水平分割线(所有
hr { height: .5em; background: currentColor;}
You might have noticed similar behavior with many existing properties. For example, if you specify a border with no color, it automatically gets the text color. This is because currentColor is also the initial value of many CSS color properties: border-color , the text-shadow and box-shadow colors, outline-color , and others.
你可能已经注意到了,很多已有的属性也具有类似的行为。举例来说,如果你没有给边框指定颜色,它就会自动地从文本颜色那里得到颜色。这是因为 currentColor 本身就是很多 CSS 颜色属性的初始值,比如 border-color 和 outline-color ,以及 text-shadow 和 box-shadow 的颜色值等等。
In the future, when we get functions to manipulate colors in native CSS, currentColor will become even more useful, as we will be able to use variations of it.
在未来,当我们在原生 CSS 中拥有处理颜色的函数后, currentColor 就会变得更加有用了,因为我们可以用这些函数来产生它的各种深浅明暗的变体。
While most authors are aware of the inherit keyword, it is often forgotten. The inherit keyword can be used in any CSS property and it always corresponds to the computed value of the parent element (in pseudo-elements that is the element they are generated on). For example, to give form elements the same font as the rest of the page, you don’t need to re-specify it, just use inherit :
尽管绝大多数开发者都知道有 inherit 这个关键字,但还是很容易遗忘它。 inherit 可以用在 任何 CSS 属性中,而且它总是绑定到父元素的计算值(对伪元素来说,则会去取生成该伪元素的宿主元素)。举例来说,要把表单元素的字体设定为跟页面的其他部分相同,你并不需要重复指定字体属性,只需利用 inherit 的特性即可:
input, select, button { font: inherit; }
Similarly, to give hyperlinks the same color as the rest of the text, use inherit :
与此类似,要把超链接的颜色设定为跟页面中其他文本相同,还是要用 inherit :
a { color: inherit; }
The inherit keyword can often be useful for backgrounds as well. For example, to create speech bubbles where the pointer automatically inherits the background and border ( Figure 1.8 ):
这个 inherit 关键字对于背景色同样是非常有用的。举个例子,在创建提示框的时候,你可能希望它的小箭头能够自动继承背景和边框的样式( 图 1.8 ):
.callout { position: relative; }.callout::before { content: ""; position: absolute; top: -.4em; left: 1em; padding: .35em; background: inherit; border: inherit; border-right: 0; border-bottom: 0; transform: rotate(45deg);}
图 1.8
A speech bubble where the pointer gets the background color and border from the parent
提示框的小箭头从父元素那里获取了背景色和边框样式。
The human eye is far from being a perfect input device. Sometimes accurate measurements result in looking inaccurate and designs need to account for that. For example, it’s well known in visual design literature that our eyes don’t perceive something as being vertically centered when it is. Instead, it needs to be slightly above the geometrical middle to be perceived as such. See that phenomenon for yourself, in Figure 1.9 .
人类眼睛并不是一台完美的输入设备。有时候精准的尺度看起来并不精准,而我们的设计需要顺应这种偏差。举一个在视觉设计领域广为人知的例子吧,我们的眼睛在看到一个完美垂直居中的物体时,感觉它并不居中。实际上,我们应该把这个物体从几何学的中心点再稍微向上挪一点儿,才能取得理想的视觉效果。来亲身体验一下这件怪事儿吧(请看 图 1.9 )。
图 1.9
In the first rectangle, the brown square is mathematically vertically centered, but doesn’t look so; in the second one, it is actually placed slightly above the geometrical center, but it looks more centered to the human eye
在第一个矩形中,棕色方块在数学层面上是完美垂直居中的,但看起来并不是这样;在第二个矩形中,方块从几何中心向上轻微移动了一点儿,但它在人类的眼睛看来却是恰好居中的。
Similarly, in type design, it is well known that round glyphs such as “O” need to be slightly larger than more rectangular glyphs, as we tend to perceive round shapes as smaller than they actually are. Check that out for yourself in Figure 1.10 .
与此类似,在字体设计领域广为人知的是,圆形的字形(比如 “0”)跟矩形字形相比,需要稍微放大一些,因为我们倾向于把圆形感知得比它实际的尺寸更小一些。在 图 1.10 中你也可以体验一下。
图 1.10
The circle looks smaller, but its bounding box is exactly the same as the square
円は小さく見えますが、実際には正方形とまったく同じ幅と高さを占めます。
このような目の錯覚は、あらゆる形式のビジュアル デザインで非常に一般的であり、考慮する必要があります。非常に一般的な例としては、テキストの量に関係なく、この問題が存在します。単語または複数の段落に同じ量のパディングを指定すると、図 1.11 が示すように、実際には文字の形が上部よりも側面の方がはるかに直線的になるためです。そのため、私たちの目はその余分なスペースを余分なパディングとして認識します。そのため、同じものとして認識させたい場合は、パディングのない部分を指定する必要があります。これにより生じる違いがわかります。 図 1.12 .
これらの視覚的な錯覚は、あらゆる形式の視覚デザインに遍在しており、的を絞った調整が必要です。非常に一般的な例は、テキスト コンテナーにパディングを設定することです。この問題は、コンテンツ テキストが 1 つの単語であっても、複数の段落であっても、どれだけ長くても発生します。コンテナの 4 つの側面に同じパディングを割り当てた場合、図 1.11 が示すように、実際の効果は均等に見えません。その理由は、文字の形状は両端はきれいですが、上下がギザギザになる傾向があり、これらのギザギザの隙間が余分な詰め物として目に認識されるためです。したがって、4 辺すべてのパディングを基本的に同じにしたい場合は、上下のパディングを減らす必要があります。この違いは、図 1.12 で確認できます。
図 1.11
テキストを含むコンテナーの 4 辺すべてに同じパディング (ここでは .5em) を指定すると、上下の辺が大きく見えます
コンテナーの 4 辺すべてに同じパディングを指定するテキスト付き (ここでは .5em が使用されています) ですが、実際には上下のスペースがはるかに多く、左右のスペースが少ないように見えます。
図 1.12
左側と右側に大きなパディング (ここでは .3em .7em ) を指定すると、より均一に見えます
左右のパディングを増やすと (ここにパディング属性が記述されています) .3em .7em のように)、明らかにより統一されているように見えます。
レスポンシブ Web デザインについて
レスポンシブ Web デザイン (RWD) は、近年非常に人気が高まっています。しかし、ほとんどの人は Web ページの「応答性」がいかに重要であるかについて話し続けるだけで、レスポンシブ デザインで適切な仕事をする方法を詳しく掘り下げる人はほとんどいません。
一般的な方法は、複数の解像度で Web サイトをテストし、発生する問題を修正するためにメディア クエリをどんどん追加することですが、
毎回のメディア クエリは将来の CSS 変更にオーバーヘッドを追加する ため、軽々しく追加するべきではありません。 CSS コードを編集するには、メディア クエリが適用されるかどうかを確認する必要があり、場合によってはそれらも編集する必要があります。メディア クエリを追加すると、CSS コードがより脆弱になります
。複数の異なる解像度を持つ Web サイトにメディア クエリ (メディア クエリ) ルールを追加して、それらの解像度での Web サイトの問題を修正します。ただし、将来の CSS の変更では、メディア クエリごとにコストが増加します。このコストは簡単に増加すべきではありません。将来的には、CSS コードを変更するたびに、これらのメディア クエリを変更する必要があるかどうかを 1 つずつ確認する必要があり、場合によっては、これらのメディア クエリの設定を順番に変更することも必要になる場合があります。これは私たちに見落とされがちですが、その影響は無限にあります。追加するメディア クエリが増えるほど、CSS コードは少なくなります。
メディア クエリが悪い習慣だと言っているわけではありません正しく使用すれば、メディア クエリは不可欠になる可能性があります。 ただし、メディア クエリは、Web サイトのデザインを柔軟にする試みがすべて失敗した後、またはより小さなビューポートまたはより大きなビューポートでデザインの側面を完全に変更したい場合 (例: サイドバーを水平にするなど)、メディア クエリはすべて特定のしきい値 (別名「ブレークポイント」) に関する問題を継続的に解決しないためです。そして、コードの残りの部分が柔軟になるように書かれていない限り、メディアクエリは特定の解決策のみを修正し、本質的に問題を根本的に解決します。
これは、メディア クエリが悪い習慣だと言っているわけではありません。 正しく使用されている限り、それらは強力なツールです。ただし、これは最後の手段としてのみ使用してください。たとえば、Web サイトを柔軟で柔軟性のあるものにしたいが、他のすべての試みが失敗した場合、または Web サイトのデザイン形式を大幅に変更したい場合などです。ビューポートを小さくします (たとえば、サイドバーを水平レイアウトに変更します)。私がこのように言う理由は、メディア クエリでは問題が継続的に解決されるわけではないからです。これらは、いくつかの特定の手順 (「ブレークポイント」とも呼ばれます) に基づいて機能します。スタイル コードのほとんどが柔軟な方法で記述されていない場合、メディア クエリで実行できるのは、特定の問題を解決することだけです。敷物の下のゴミを掃きます。
{ヒント}
メディア クエリでピクセルの代わりに em を使用することを検討してください。これにより、必要に応じてテキスト ズームでレイアウト変更をトリガーできるようになります。
メディア クエリでピクセルの代わりに em を使用することを検討してください。これにより、必要に応じてテキストのスケーリングによってレイアウトの変更をトリガーできるようになります。
もちろん、メディア クエリのしきい値は特定のデバイスによって決定されるべきではなく、Web サイトには非常に多くの異なるデバイスがあるため (特に将来のデバイスを考慮した場合)、デザイン自体によって決定されるべきであることは言うまでもありません。デスクトップ上の Web サイトはどのようなサイズのウィンドウでも表示される可能性があるため、あらゆる解像度で適切に表示される必要があります。デザインがあらゆるビューポート サイズで適切に機能するという確信がある場合、特定のデバイスの解像度を誰が気にするでしょうか。
もちろん、上記で言及されていないことが 1 つあります。 メディア クエリのブレークポイントは、特定のデバイスによって決定されるべきではなく、 設計自体によって決定される必要があります。それは、Web サイトが対応する必要があるデバイスが非常に多いため (特に、将来のデバイスのことを考えると) だけでなく、デスクトップ上の Web サイトが任意のサイズのウィンドウで表示される可能性があるためでもあります。デザインがどのようなビューポート サイズでも適切に機能するという自信があるのであれば、それらのデバイスの正確な解像度を誰が気にするでしょうか?
XXXX で説明されている原則に従うことも、メディア クエリで多くの宣言をオーバーライドする必要がなくなり、実質的に発生するオーバーヘッドを最小限に抑えることができるため、これにも役立ちます。 」段落 (ページ {$page$})
ここで説明されている原則は、メディア クエリで同じ数の宣言をカバーする必要がなく、本質的にメディア クエリで発生するメンテナンス コストを軽減できるため役立ちます。不必要なメディア クエリを回避するためのヒントをさらにいくつか紹介します:
不必要なメディア クエリを回避するためのヒントをさらにいくつか紹介します:
それが不可能な場合は、ビューポート相対単位を使用してください。 vw 、 vh 、 vmin 、 vmax )、ビューポートの幅または高さの一部に解決されます。
固定長の代わりにパーセンテージの長さを使用します。これが不可能な場合は、値がビューポートの幅または高さのパーセンテージに解決されるビューポート相対単位 ( vw 、 vh 、 vmin 、および vmax ) の使用も試みる必要があります。
より大きな解像度で固定幅が必要な場合は、 width ではなく max-width を使用します。これにより、メディアクエリなしでも小さな解像度に適応できます。 width の代わりに max-width を使用すると、を使用せずに小さな解像度に対応できます。メディアクエリ。
img、object、video、iframe などの置換された要素の max-width を 100% に設定することを忘れないでください。) max-width の値を 100% に設定します。
背景画像がコンテナ全体をカバーする必要がある場合、background-size:cover はコンテナのサイズに関係なくそれを維持するのに役立ちます。ただし、帯域幅は無制限ではなく、含めることが常に賢明であるとは限らないことに留意してください。モバイル デザインで CSS を介して縮小される大きな画像。
背景画像がコンテナを完全に覆う必要がある場合、コンテナのサイズに関係なく、background-size: cover 属性でこれを行うことができます。ただし、文字列も厳しくする必要があります。帯域幅は無制限ではないため、CSS を使用してモバイル Web ページ内の大きな画像の表示を減らすのは賢明ではないことがよくあります。
When laying out images (or other elements) in a grid of rows and columns, let the number of columns be dictated by the viewport width. Flexible Box Layout (a.k.a. Flexbox) or display: inline-block and regular text wrapping can help with that.
当图片(或其他元素)以行列式进行布局时,让视口的宽度来决定列的数量。弹性盒布局(即 Flexbox),或者 display: inline-block 加上常规的文本折行行为,都可以实现这一点。
When using multi-column text, specify column-width instead of column-count , so that you get one column only in small resolutions.
在使用多列文本时,指定 column-width (列宽)而不是指定 column-count (列数),这样它就可以在较小的屏幕上自动显示为单列布局。
In general, the idea is to strive for liquid layouts and relative sizing between media query breakpoints . When a design is sufficiently flexible, making it responsive shouldn’t take more than a few short media queries. The designers of Basecamp wrote about this very matter in late 2010:
总的来说,我们的思路是尽最大努力 实现弹性可伸缩的布局,并在媒体查询的各个断点区间内指定相应的尺寸 。当网页本身的设计足够灵活时,让它变成响应式应该只需要用到一些简短的媒体查询代码。Basecamp 的设计师在 2010 年曾写过这种非常规情况:
“As it turned out, making the layout work on a variety of devices was just a matter of adding a few CSS media queries to the finished product. The key to making it easy was that the layout was already liquid, so optimizing it for small screens meant collapsing a few margins to maximize space and tweaking the sidebar layout in the cases where the screen is too narrow to show two columns.”
—— Experimenting with responsive design in Iterations
“结果我们发现,想让网页在一堆不同的设备上合理展示,只需要在最终产品上添加一丁点儿 CSS 媒体查询就可以了。这件事情之所以这么简单,关键在于我们的布局原本就是弹性可伸缩的。因此,优化网页在小屏幕上的表现,其实只意味着把一些外边距收拢到最小程度,然后再把因为屏幕太窄而无法显示成双列的侧栏调整为单列布局而已。”
{--:}—— 在 Iterations 中实践响应式设计
If you find yourself needing a boatload of media queries to make your design adapt to smaller (or larger) screens, take a step back and reexamine your code structure, because in all likelihood, responsiveness is not the only issue there.
如果你发现你自己需要一大堆的媒体查询才能让你的设计适应大大小小不同的屏幕,那不妨往后退一步,重新审视你的代码结构。因为在所有的情况下,响应式都不是唯一需要考虑的因素。
As you probably know, the following two lines of CSS are not equivalent:
你可能知道,以下两行 CSS 代码并不是等价的:
background: rebeccapurple;
background-color: rebeccapurple;
The former is a shorthand and will always give you a rebeccapurple background, whereas the element with the longhand ( background-color ) could end up with a pink gradient, a picture of a cat, or anything really, as there might also be a background-image declaration in effect. This is the problem when you mainly use longhands: you are not resetting all the other properties that could be affecting what you’re trying to accomplish.
前者是简写,它可以确保让你得到 rebeccapurple 纯色背景;但如果你用的是展开式的单个属性( background-color ),那这个元素的背景最终有可能会显示为一个粉色的渐变图案、一张猫的图片、或任何东西,因为同时可能会有一条 background-image 声明在起作用。通常在使用展开式属性的写法时,会遇到这样的问题:展开式写法并不会帮助你清空所有相关的其他属性,从而可能会干扰你想要达到的效果。
You could of course try to set all the longhands and call it a day, but then you might forget some. Or the CSS WG might introduce more longhands in the future, and your code will have failed to reset those. Don’t be afraid of shorthands. It is good defensive coding and future-proofing to use them, unless we intentionally want to use cascaded properties for everything else, like we did for the colored button variants in the XXXXXXXXXXXX .
当然你可以把 所有的展开式属性 全都设置一遍,然后收工,但你可能会漏掉几个没写全。又或者,CSS 工作组可能会在未来引入更多的展开式属性,那时你的代码就无法完全覆盖它们了。不要不敢用简写属性。合理使用简写 是一种良好的防卫性的编码方式,可以抵御未来的风险 。当然,如果我们 很明确地要去覆盖某个具体的展开式属性 并保留其他相关样式,那就用展开式属性,就像我们在 “{$section$}” 段落(第 {$page$} 页) 中为了得到按钮的其他颜色版本所做的那样。
Longhands are also very useful in combination with shorthands, to make code DRY-er in properties whose values are a comma-separated list, such as the background properties. This is best explained with an example:
展开式属性与简写属性的配合使用也是非常有用的,可以让代码更加 DRY。对那些接受一个用逗号分隔的列表的属性(比如 background )来说,尤其如此。下面的例子可以很好地解释这一点:
background: url(tr.png) no-repeat top right / 2em 2em, url(br.png) no-repeat bottom right / 2em 2em, url(bl.png) no-repeat bottom left / 2em 2em;
Notice how the background-size and background-repeat values are repeated three times, despite being the same for every image. We can take advantage of CSS list expansion rules which say that if only one value is provided, it is expanded to apply to every item in the list , and move these repeated values to longhands:
请注意 background-size 和 background-repeat 的值被重复了三遍,尽管每层背景的这两个值确实是相同的,但这仍然是一种冗余。其实我们可以从 CSS 的 “列表扩散规则” 那里得到好处——它的意思是说, 如果只为某个属性提供了一个值,那它就会扩散并应用到列表中的每一项 。因此,我们可以把这些重复的值从简写属性中抽出来写成一个展开式属性:
background: url(tr.png) top right, url(br.png) bottom right, url(bl.png) bottom left;background-size: 2em 2em;background-repeat: no-repeat;
Now we can change the background-size and background-repeat with only one edit instead of three. You will see this technique used throughout the book.
现在,我们只需要在一处修改,就可以改变所有的 background-size 和 background-repeat 了。你会发现这个技巧在本书中的使用非常普遍。
{小花絮}
You might have noticed in the shorthand and longhand example that specifying background-size in the background shorthand requires also providing a background-position (even if it’s the same as the initial one) and using a slash ( / ) to separate them. Why do some shorthands have such weird rules?
你可能已经注意到前面那个背景属性简写的例子了:在 background 简写属性中指定 background-size 时,需要同时提供一个 background-position 值(哪怕它的值就是其初始值也需要写出来),而且还要使用一个斜杠( / )作为分隔。为什么有些简写的语法如此怪异?
This is almost always done for disambiguation purposes. Sure, in the example here, it’s obvious that top right is a background-position and 2em 2em a background-size regardless of their ordering. However, think of values like 50% 50% . Is it a background-size or a background-position ? When you are using the longhands, the CSS parser knows what you mean. However, in the shorthand, the parser needs to figure out what that 50% 50% refers to without any help from the property name. This is why the slash is needed.
这通常都是为了消除歧义。是的,在这个例子中,很显然 top right 是 background-position ,而 2em 2em 是 background-size ,不管它们的顺序如何。但是,请设想一下 50% 50% 这样的值。它到底是 background-size 还是 background-position 呢?当你在使用展开式属性时,CSS 解析器是知道你的意图的。但当你使用简写属性时,解析器需要在没有属性名提示的情况下弄清楚 50% 50% 到底是指什么。这就是为什么需要引入这个斜杠。
For most shorthands, there is no such disambiguation issue and their values can be specified in any order. However, it’s always good practice to look up the exact syntax, to avoid nasty surprises. If you are familiar with regexes and grammars, you could also check the grammar for the property in the relevant specification, which is probably the quickest way to see if there is a specific ordering.
省略された属性の大部分では、そのような曖昧さの問題は存在しないため、多くの場合、省略された属性の複数の値を任意に配置できます。ただし、落とし穴にはまらないように、文法を自由に調べる習慣を身につけることをお勧めします。正規表現や標準化された文法説明 (文法) に精通している場合は、関連する仕様で文法説明を直接照会することもできます。特定の属性の値に明確な順序要件があるかどうかを判断したい場合は、次のようになります。最良の方法。
LESS 、 Sass 、 Stylus などの CSS プリプロセッサについて聞いたことがあるでしょう。これらは、変数、ミックスイン、関数、ルールのネスト、色の操作など、CSS を作成するための便利な機能を提供します。 Stylus、Sass、LESS などの CSS プリプロセッサを聞いた。これらは、変数、ミックスイン、関数、ルールのネスト、色処理など、CSS を記述するための便利な機能を提供します。
適切に使用すると、CSS 自体に制限がありすぎてそれができない場合に、大規模なプロジェクトでコードをより柔軟に保つのに役立ちますが、堅牢で柔軟な DRY CSS をコーディングしようと努めても、制限に遭遇してしまうことがあります。ただし、プリプロセッサには独自の問題もいくつかあります。
正しく使用すると、大規模なプロジェクトでコードをより柔軟にすることができますが、CSS 自体にはこの点で大きな制限があります。コードの堅牢性、柔軟性、DRY を追求する限り、この点で CSS の限界を感じることになります。ただし、プリプロセッサは完璧ではありません:
を見失うことがあります。そして複雑さは制御不能になる可能性があります。単純明快なソースコードであっても、コンパイル後には空から降ってくる巨大な獣と化すこともあります。
開発ツールに表示される CSS コードは自分が作成したソース コードではないため、デバッグはより困難になります。ただし、より多くのデバッグ ツールが
レイテンシ が発生しますが、コードを CSS にコンパイルするのに 1 秒ほどかかり、結果をプレビューする前に待機する必要があります 。
遅延 が発生します。これらは一般に高速ですが、ソース コードを CSS にコンパイルするにはまだ 1 秒近くかかり、コードの効果をプレビューするにはこの時間を待つ必要があります。
漏れやすい抽象化の法則を忘れないようにしましょう: 「すべての非自明な抽象化は、ある程度は漏れがあります。」独自のバグ
另外,别忘了还有 抽象泄漏法则 :“所有重大的抽象机制在某种程度上都存在泄漏的情况。” 预处理器是由人类写出来的,就像所有由人类写出来的大型程序一样, 它们有它们自己的 bug 。这些 bug 可能会潜伏很久,因为我们很少会怀疑预处理器的某个 bug 才是我们 CSS 出错的幕后元凶。
In addition to the issues listed here, preprocessors also pose the risk of making authors dependent on them, perpetuating their use even when unnecessary, such as in smaller projects or in the future, after their most popular features have been added to native CSS. Surprised? Yes, many preprocessor-inspired features have been making their way into pure CSS :
除了上面列出的这些问题,预处理器还可能导致这种风险——网站开发者们可能会不自觉地 “依赖” 和 “滥用”。因为在某些时候,预处理器并不必要,比如在小型项目中,或者在未来,说不定预处理器最受欢迎的那些特性都被加入到原生 CSS 中了。很惊讶吗?没错, 很多受预处理器启发的特性都已经以各种方式融入到原生 CSS 中了 :
There is already a draft about variable-like custom properties, under the title of CSS Custom Properties for Cascading Variables .
已经有一份关于(跟变量类似的)自定义属性的草案了,名称叫作 CSS 自定义属性暨层叠式变量 。
The function calc() from CSS Values & Units Level 3 not only is very powerful for performing calculations, but also very well supported, even today.
CSS 值与单位(第三版)中的 calc() 这个函数,不仅在处理运算时非常强大,而且已经得到了广泛的支持,当下可用。
The color() function in CSS Color Level 4 will provide means to manipulate colors.
CSS 颜色(第四版) 引入的 color() 函数将会提供颜色运算方法。
There are several serious discussions in the CSS WG about nesting, and even a draft spec (ED) existed about it in the past.
关于嵌套,CSS 工作组内部正在进行一些正式的讨论,甚至以前还有过一份相关的草案(ED)。
图 1.13
Myth is an experimental preprocessor that emulates these native CSS features, instead of introducing proprietary syntax, essentially acting like a CSS polyfill
Myth 是一款实验性质的预处理器,它只去模拟上述这些原生的 CSS 新特性,而不是引入私有语法。它本质上扮演了 CSS polyfill 的角色。
Note that native features like these are generally much more powerful than the ones provided by preprocessors , as they are dynamic. For example, a preprocessor has no clue how to perform a calculation like 100% - 50px , because the value percentages resolve to is not known until the page is actually rendered. However, native CSS calc() has no trouble evaluating such expressions. Similarly, variable use like the following is not possible with preprocessor variables:
请注意这些原生特性通常会 比预处理器提供的版本要强大得多 ,因为它们是动态的。举个例子,预处理器完全不知道如何完成 100% - 50px 这样的计算,因为在页面真正被渲染之间,百分比值是无法解析的。但是,原生 CSS 的 calc() 在计算这样的表达式时没有任何压力。与此类似,下面这样的变量玩法在预处理器中是不可能做到的:
{原书注释!}
Don’t forget that native CSS features like these can be manipulated through scripting too. For example, you could use JS to change the value of a variable.
不要忘了这样的原生 CSS 特性也可以通过脚本来操纵。比如说,你可以用 JS 来改变一个变量的值。
ul { --accent-color: purple; }ol { --accent-color: rebeccapurple; }li { background: var(--accent-color); }
Can you see what we did there? The background of list items in ordered lists will be rebeccapurple , whereas the background of list items in unordered lists will be purple . Try doing that with a preprocessor! Of course, in this case, we could have just used descendant selectors, but the point of the example was to show how dynamic these variables will be.
このコードの意図が明確にわかりますか?順序付きリストのリスト項目の背景色は rebeccapurple ですが、順序なしリストのリスト項目の背景色は purple になります。プリプロセッサを使ってみてはいかがでしょうか?もちろん、この例では子孫セレクターを直接使用できますが、この例のポイントは CSS のネイティブ変数のダイナミクスを示すことです。
前述のネイティブ CSS 機能のほとんどは現在十分にサポートされていないため、保守性が重要な場合には、多くの場合、プリプロセッサの使用は避けられません (そうすべきです)。私のアドバイスは、すべてのプロジェクトを純粋な CSS で開始し、それが使い始められるようになったときです。 DRY を維持するのは不可能なので、プリプロセッサの使用に切り替えてください。プリプロセッサに完全に依存したり、実際に必要でないときにプリプロセッサを使用したりすることを避けるために、プリプロセッサの使用は、デフォルトで実行される無分別な最初のステップではなく、意識的な決定である必要があります。新しいプロジェクトごとに。
上記のネイティブ CSS 機能のほとんどは現時点では十分にサポートされていないため、多くの場合、保守性が重要である場合 (実際にそうなのですが)、プリプロセッサの使用は避けられません。私のアドバイスは、すべてのプロジェクトを純粋な CSS で開始し、コードが DRY で制御不能になり始めた場合にのみプリプロセッサ ベースのアプローチに切り替えることです。起こり得る「依存」や「乱用」を避けるために、プリプロセッサの導入の問題については冷静に判断する必要があります。各プロジェクトの開始時に盲目的で惰性に従ってはいけません。
疑問に思っている方のために (最初の章をまだ読んでいない方のために)、この本のスタイルは SCSS で書かれています が、最初は純粋な CSS として開始され、コードが複雑になりすぎて読み取れなくなった場合にのみ切り替えられました。 CSS とそのプリプロセッサは Web 専用だなんて誰が言ったのでしょう
まだご存じないかもしれませんが、もう一度言っておきます、この本のスタイルは で書かれています。 SCSS。ただし、スタイリング コードは純粋な CSS として開始され、コードが複雑になりすぎて保守できなくなった場合にのみ SCSS に切り替わりました。 CSS とプリプロセッサは Web ページでのみ使用できると誰が言ったのでしょうか?