关于CSS需要知道的10件事

原文: http://dsheiko.com/weblog/10-things-to-need-to-know-about-css
CSS may look as a simple language. In fact it can be simple only to use, but definitely not simple to maintain.
CSS看起来是个简单的语言,实际上只是使用较为简单,但是很显然维护它并不简单。

Observing that the maximum number of people who can productively simultaneously work on CSS is one – @threedaymonk
The skills required to write good CSS code are by and large the same skills required to write good code in general. – Lea Verou
写出好的CSS所要求的技能大体上和写出好代码要求的技能是相同的。

Everybody who used to work on a large-scale projects knows how hard it can be to keep constantly growing CSS sources readable and consistent, styles reusable and loosely coupled. Moreover while going responsive web design (RWD) we also deal with increasing cyclomatic complexity. Learning from own experience I collected 10 vital principles that help turning your styles into efficient and highly maintainable code.

每个在大型项目中工作的人都应该知道对于大量增长的CSS资源保持可读性和可维护性是多么困难。样式的可重用性和松耦合。此外在响应式(RWD)web开发中还要处理持续增长的圈复杂度,从自己的项目中所积累的经验,我总结了10条非常重要的准则可以帮助你的样式更高效并且高度的持续和维护。

1.要知道浏览器是从右向左读取样式选择器的 (Be aware that browser reads selectors from right to left)

It is a fundamental fact, yet surprisingly a little known: browsers read selectors from right to left. It means harmlessly looking selectors like .feed nav ul li h2 are unacceptably inefficient. In order to solve this riddle browser will find first all the h2 in the document, then all li and so forth until it comes to .feed and filters formerly found elements to compose a matching node list. This problem can be avoided by shortening selector path to the element (e.g. .feed-list-heading). Yet we still can do nesting when using a child selector. It gives considerably good efficiency because browser needs to check only one level higher in the DOM and then stops (e.g. .feed-list > li > h2)
这是一个基本的事实,然而令人惊讶的是很少人知道:浏览器从右至左读取样式选择器。 这意味着看起来没有什么不好的选择器(.feed nav ul li h2 )实际上效率低到不能忍!!!!!为了解开你写的这个鬼,浏览器首先在页面文档中寻找所有的h2标签,接着寻找所有的li标签,以此类推直到找到了类选择器.feed 然后过滤器终于找到了这个选择器匹配的页面节点。 这个问题可以通过缩短选择器的路径来解决(比如:.feed-list-heading)但我们也可以嵌套使用子选择器,它可以相当的高效,因为更高一层的dom然后就停止了,比如(.feed-list > li > h2)
延伸阅读(Further Reading)

* [Beware of Selector Nesting in Sass](http://www.sitepoint.com/beware-selector-nesting-sass/)

2. 坚持基于组件的CSS (Keep to component-based CSS)

How do we style a web application? There is still a method of going from element to element and styling each in place. Easy, isn’t it? Don’t do it! Besides that you repeat yourself again and again you will end up with a viscous architecture resisting to any change. Instead you ought to look for repeating patterns in the PSDs and extract reusable components such as navbar, breadcrumbs, dropdowns, thumbnail, panel. Components are supposed to be small and independent. Let’s say we have a number of button-like controls across the application. So we create an abstract component identified by class name .btn. The corresponding rule-set describes look & feel applicable to any button in the application.
怎样写一个web APP的样式,一个一个元素的修饰给他们写样式不是一种方法吗,简单不是吗? 不要这样做,这样你在一遍一遍的重复的结构会抵制任何的改动。应该先在PSD设计文档中寻找重复的模块然后把这些组件提取出来,比如导航,面包屑,下拉菜单,面板等等。组件应该非常小,并且是独立的,假设我们有一个有很多按钮的控制的应用,所以我们可以用类.btn命名一个抽象的组件,那么它相关的样式描述和感觉应该能够被应用中的任何按钮采用。

.btn {
  cursor: pointer;
  -webkit-user-select: none;
  text-align: center;
  white-space: nowrap;
  border-width: 0.1rem;
  border-radius: 0.4rem;
  display: inline-box;
}

Then we add rules per each concrete button type:
然后给每个具体的按钮添加相应样式规则

.btn-primary {
  color: #fff;
  background-color: #428bca;
  border-color: #357ebd;
  border-style: solid;
}

Depending on location we achieve the intended style on an element by combining CSS classes:
根据位置 然后将风格和元素两个CSS结合:

<button class="btn btn-primary">Submitbutton>

There are a few standardized approaches for component-based CSS architecture SMACSS ,OOCSS, ACSS, BEM . It’s a matter of personal choice which one to follow.
So you adopt any of them, you can take best practices of a few mixed ( see for example) or be on your own way.
这里有一些基于组件的标准化方法的CSS文章: SMACSS OOCSS ACSS BEM, 使用哪一种其实是个人的选择,你可以采用任何一个, 那最好先练练一些混合的例子,或者使用你自己的方法。
这里有一些基于组件的标准化方法的CSS文章: SMACSS OOCSS ACSS BEM, 使用哪一种其实是个人的选择,你可以采用任何一个, 那最好先练练一些混合的例子,或者使用你自己的方法。
延伸阅读(Further Reading)

* [\[Introducing CCSS (Component CSS)\]](http://www.sitepoint.com/introducing-ccss-component-css/)()

3. 将你的CSS结构模块化 (Structure your CSS into modules)

Did it occur to you to look thought a single-file style-sheet of a large-scale project? It looks inscrutable. A complex problem, though, can be broken into simpler tasks. So the entire system becomes easier to debug, update and modify. We can split the whole style-sheet into multiple files so that every file represented a component. The application style-sheet we will do by combining required components:
你有没有想过通过单一的样式表文件来构建一个大型的项目? 看起来挺不可思议的。但是任何一个复杂的问题都可以拆分成简单的任务,所以整个系统变得更加容易调试,更新和修改。 我们可以将整个样式表拆分成为单个的文件,这样每一个文件代表一个组件。 这样应用的样式表将由所需要的组件组合而成。

/* app.css */
@import "./module/page-header.css";
@import "./module/breadcrumbs.css";
@import "./module/panel.css";

So to modify a style we don’t need to go through the monstrous source code file, but confine the problem scope to a single component file. The bad news is that application style-sheet now produces numerous HTTP requests during the page load. Yet it is no problem if you use a CSS preprocessor. Preprocessors compile all the declared dependencies into a single output CSS file.
这样在修改一个样式的时候再不需要去浏览整个恐怖的样式文件了,只需要确定这个问题的范围,就可以去组件的样式文件中找了。 坏消息是样式文件在页面加载的过程中需要很多的http请求,当然你使用CSS预处理那就没有问题了,预处理可以将所有的依赖文件结合输出到一个文件中。

4.将软件设计的原则应用在CSS中 ( Apply software design principles to CSS)

CSS is no programming language yet it is a code that must be maintainable. The very same principles we are used in programming languages encapsulation, loose coupling and reusability apply to CSS:
Reusability
Style the components, not a page, so that you could apply once created style an infinite amount of times across the project. Do not repeat rules while styling, but leverage cascade or mix-in styles
css不是编程语言,因此它的代码必须是可维护的,我们在其他编程语言中所使用的封装是同样的原则,松耦合和可重用性同样适用于CSS:

可重用性
组件的样式,不是一个页面,所以你可以创建一次样式并且可以在整个项目中使用无限次。 不要写重复的样式规则,但可以使用连级或者混合的风格。

松耦合 标签独立 Loose Coupling (Tag Independence)

Avoid qualified selectors (prepended with tag). Thus you will gain additional agility in moving classes around components. Examine this, you have a form to style. The form has a submit button. You style it as button.btn. Everything seems fine until you need to set style for download button. It must look like a button, but it’s a link and button.btn won’t match there. With tag-independent selectors (.btn) you can reuse styles regardless of tag.

避免使用受限的标签选择器,这样你就获得了在组件中移动类选择器的灵活性。拷问,假设你有一个表单的样式,表单有一个提交的按钮,你用button.btn来修饰这个按钮。 在你需要修饰一个下载的链接按钮前,所有的一切似乎都不错,这个链接必须要有一个按钮的样子,但是button.btn的修饰并不能满足它的需求,所以使用标签无关的选择器就可以使样式与标签独立,这样就可以忽视标签并重用样式。

松耦合 位置独立 Loose Coupling (Location Independence)

Avoid long selectors with descendant/child combinators (.feed nav ul li h2). Long selectors besides harmful affect on selector performance mean that style rule-set is tied to particular location in the DOM. Independent selectors allow us to move components around our markup more freely.
We know “5 first principles” of computer programming. Whatever strange it may sound for a declarative language, Miller Medeiros has shown how S.O.L.I.D. applies to CSS.
It may be controversial to consider CSS in terms of LSP, ISP and DIP (it makes a perfect sense though if you give it a second though). Yet the first two principles are essential for maintainable CSS.

避免使用很长的子/后代选择器组合,像(.feed nav ul li h2)。长的选择器不仅会损耗性能,而且它的规则会和DOM的特定节点绑定在一起。独立的选择器允许我们更自由的移动组件标记。
我们都知道计算机编程中的五个一的原则,但是它对于标记性的语言很奇怪,Miller Medeiros表明了如何在CSS中采用它。
依据LSP的方式考虑CSS可能是有争议的,ISP and DIP(我也不懂事啥东西) 前两个原则对于维护可持续的CSS至关重要。

单一责任原则 The Single Responsibility Principle (SRP)

The principle implies that A class should have one, and only one, reason to change. In CSS we have
这意味着在CSS中我们的一个类应该有一个原则 而且只有一个理由去改变。

.btn {
  cursor: pointer;
  -webkit-user-select: none;
  text-align: center;
  white-space: nowrap; 
  border-radius: 0.4rem;
}
.btn-primary {
  color: #fff;
  background-color: #428bca;
  border-color: #357ebd;
  border-style: solid;
}
.btn-lg {
  padding: 1rem 1.6rem;
  font-size: 1.8rem;
  line-height: 1.33;
  border-radius: 0.6rem;
  border-width: 0.1rem;
}

Here every class represents only one concept. .btn states for button base style, .btn-primary for a concrete cosmetic style and .btn-lg for the box-model. By combining these classes we have a number of options like:
这里的每一个类只有一个内容, .btn代表了按钮的基本样式, .btn-promary是具体的修饰样式,.btn-lg是为盒模型的,考虑这些样式类的结合,我们有以下的几种组合方式:

<button class="btn btn-primary btn-lg">OKbutton>
<button class="btn btn-secondary btn-lg">Cancelbutton>
<button class="btn btn-primary btn-small">Xbutton>

If requirements change, we need to change the only class rules and all the buttons of the web application will change consistently.
如果有需求的变化,我们只需要改变一个类的规则,然后整个Web应用的样式都会一致的改变。

打开关闭原则 The Open/Closed Principle (OCP)

The principle states that you should be able to extend a classes behavior, without modifying it.
In CSS it means that we have to design base class style so that we could easy extend it without its modification. If we have a base .btn class defining a border, but want any button of .toolbarcontext to go with no border, we can only reset that border rule.

这个原则代表你应该可以扩展一个类的行为而避免去修改这个类。
在CSS中这个意思就是我们需要设计基础的样式类,这样我们就能很容易的扩展它并且避免在对它本身的修改。如果我们有一个基础的.btn,.btn定义了一个边框,但是想要没有边框的按钮,只能去重置样式规则,比如

.btn {
  border: 0.1rem solid #357ebd;
}
.toolbar .btn {
  border: none;
}

这违反了打开关闭原则,我们应该增强基础类的设计而不是去修改它。

.btn {
  /* base rules */
}
.btn-outlined {
  border: 0.1rem solid #357ebd;
}

This design clarifies the intend behind the classes, besides, it doesn’t break SRP.
这个设计澄清了设计类背后想要的意图,并且没有打破单一责任规则。

延伸阅读(Further Reading ):

* Used and Abused – [CSS Inheritance and Our Misuse of the Cascade](http://www.phase2technology.com/blog/used-and-abused-css-inheritance-and-our-misuse-of-the-cascade/)

组合超越继承 Composition over Inheritance

The cascading styles suggest any rules assigned to a parent are being inherited by its descendants. It’s a great thing and, at the same time, it can make your life difficult. Consider the following example:

叠层样式规则分配给它的父节点并被后代继承这是一个伟大的事情,但是与此同时它会使你的人生更艰难, 考虑下面的例子:

/* .html */
<span class="badge">100span>
<h2><span class="badge">100span>h2>
<a><span class="badge">100span>a>
<table class="modifier-a modifier-b"><tr><td class="modifier-c"><span class="badge">100span>td>tr>table>
/* .css */
.badge {
  font-size: 1.25em;
}

Now try to predict what style will be the badge. The first line sets the font-size to 16px (browser default font size) * 1.25em = 20px, font-weight to normal and none to text decoration. The second line changes font size and weight according to h2 style (16px * 1.5em * 1.25em = 30px). Next it changes inheriting text decoration from a. In the last line we have multiple inheritance, what we have to avoid in programming “at all costs”.
In order to make styles clean and predictable we need to use composition rather than inheritance. This principle implies that complex objects should be composed from much smaller, rather than inheriting behaviour from a much larger, monolithic object.
Thinks back to our SRP example. We composed button UX component from smaller and unrelated objects.
现在试图语言它的样式,第一行设置字体大小是16像素 * 1.25是20像素, font-weight为normal,没有下划线。 第二行改变了字体大小和字重,根据h2的样式计算(16px * 1.5em * 1.25em = 30px),然后从a的继承它改变了字体的修饰,在最后一行,我们得到了非常复杂的继承关系。这是我们在编写代码中不计一切成本要避免的事情。
为了使样式更干净而且更有可预测性,我们要多使用组合而不是继承。这个原则意味着复杂的对象应该由更小的对象组合起来比用从比较大的类中继承这种行为更好。
回到我们单一责任原则的例子中,我们用更小的组件和互相独立的类组合出了按钮的用户体验。
Further Reading

* [Used and Abused – CSS Inheritance and Our Misuse of the Cascade](https://www.phase2technology.com/blog/used-and-abused-css-inheritance-and-our-misuse-of-the-cascade/)

5.记住CSS中命名东西是困难的 ( Remember that naming in CSS is hard)

There are only two hard things in Computer Science: cache invalidation and naming things. – Phil Karlton
计算机科学中有两件难事,一个是缓存失效,一个是命名一个东西 – Phil Karlton

How much time you spend looking for a most appropriate class name? If not much I don’t think you have maintainable CSS. It’s not so easy to get these names. First of all we need to came up with a strategy. Frequently used names can be split into following categories:
你有多少时间花费了寻找适合的命名上,如果不多我不认为你的CSS具有可持续性和扩展性。 确定这些名字并不容易。首先我们需要想出来一个策略,常用的命名可以分为以下的类别:
功能性的命名 (Functional class names)

<div class="is-relative is-responsive">div>

内容性的命名 (Content-based class names)

<div class="registered-user-avatar">div>

基于展现的命名 (Presentational class names)

<div class="round-box">div>

No category of the list by itself is good enough as to show selector intent as to keep to the principles we examined in the previous chapter.
A good naming convention will tell you and your team

* what an entity class represents;
* where a class can be used;
* what (else) a class might be related to.

没有类别的列表本身已经足够好了就像展示显示意图一样 坚持我们在前面章节中已经审视过的原则吧。
一个好的命名环境会告诉你以及你的团队:

*      这个类代表的是什么
*      这个类可能被用在什么地方
*      还有其他可能与这个类相关的类

You can find guidelines on naming in SMACSS, OOCSS , ACSS, BEM.
I personally keep to class names describing the objects, their modifiers and states:
你可以从 SMACSS,OOCSS,ACSS,BEM中找到相关的参考。
我个人会用类名来描述这个实体,以及他们的改变和状态:

.noun {}            // parent: .post
.noun-noun {}       // child:  .post-title
.adjective-noun {}  // example: .dropdown-button
.is-state {}        // state: is-selected, is-hidden
.adjective {}       // examples: .left, .right, .block, .inline

延伸阅读 (Further Reading)

* [Naming CSS Stuff Is Really Hard](http://seesparkbox.com/foundry/naming_css_stuff_is_really_hard)
* [thesassway.com/advanced/modular-css-naming-conventions](http://thesassway.com/advanced/modular-css-naming-conventions)

6. 使用类名来标识样式,使用ID和数据属性去绑定JavaScript (Use classes are for styling, IDs and data-attributes to bind JavaScript)

You can run into IDs used for styling in many open-source projects. Do not adopt this practice. Why?

  • ID has top specificity and no amount of chained classes can override a rule-set assigned to an id.
  • ID can be used on page only once, so we cannot make any reusable styles with an ID in selector.

你可能会在很多的开源项目中遇到用ID来设置样式的这种做法,但是不要采用这种惯例。为何?

  • ID是最有特殊性的,再多的类也没有办法覆盖ID给元素设置的样式规则。
  • ID在一个页面总只能出现一次,所以我们无法用ID选择器创造可重用的样式。

So we rather to use IDs in HTML for fragment identifiers or for JavaScript bindings. Element attributes can be also reached from CSS and they don’t have the issues enlisted above. Yet for a better separation of concerns it’s not recommended to use them in styling. When you use only classes for styling and keep IDs and attributes for JavaScript binding you get much more flexibility in moving styles across the document.
By the way, use of !important directive in most cases isn’t a good idea. But you can strengthen specificity of a selector by repeating class name:

所以我们更应该在html片段中将ID用作片段标识符或者绑定JavaScript的钩子,CSS也可以通过元素的触及到元素的属性来修饰元素这个不涉及现在的问题。 对于分离更好的关注点是不推荐在ID中使用样式。当你仅用class来修饰元素,只用ID来作为JavaScript的钩子你会获得在不同的页面文档中移动样式更高的灵活性。
顺便说一句,很多情况下直接使用!importent不是一个主意,然而你可以通过重复类选择器的名称来提高样式的优先级:

.class.class.class.class { ... }

延伸阅读 Further Reading

* [When using IDs can be a pain in the class.](http://csswizardry.com/2011/09/when-using-ids-can-be-a-pain-in-the-class/)..

7. 遵循标准流 (Follow the standard flow)

When creating a layout, we should think of working with normal flow first. The boxes under the flow act according the well-documented block and inline formatting context models. So when the parent box changes all the inner boxes adjust their positions to fit best the new layout dimension. Floating boxes are specific, nonetheless they also participate in the flow. However absolute/fixed positioned boxes are completely out of the flow. While fixed boxes we use in special cases and that is fine, but absolutely positioned boxes often replace the normal flow and there we run into the pitfalls.
我们在创建一个布局的时候,首先想到的应该是常规流。 一个在文档流中的块级和模型的表现和内联元素模型的表现。所以当父级元素改变的时候所有的内部的元素会相应的调整自己的位置来更好的适应容器的尺寸。 浮动的盒子特殊,尽管如此它们还参与到整个流中。 绝对定位和固定定位的元素完全脱离了文档流。 我们在一些特定的例子中使用固定定位很ok,但是绝对定位会经常替代常规流 我们经常在这载进陷阱。

流中的定位 Positioning boxes in the flow

Instead of absolute positioning boxes we rather rely on margins and paddings of the normal flow. Mostly it works obvious, but sometimes in cascading boxes we are getting unaccountable vertical gaps or opposite – lost spacing. You need to be aware of collapsing margins. The issue can be solved simply by setting up e.g. a transparent border.
取代绝对定位的盒子我们宁愿在常规流中依靠外边距和补白,大多数情况很明显有效果,但是有些时候相联接盒模型之间会莫名其妙的多出了垂直的间距或者相反-失去了间距。 你应该意识到外边距塌陷的问题。 这个问题也可以设置比如 透明的边框来解决。

响应式设计 Responsive design
When positioning and sizing boxes in RWD, we rely mostly on relative units such as percentage. If you want images adjusting horizontally you do:
在响应式开发中我们定位和定型一个盒模型,通常会依靠像百分比这样的相对单位。如果你想水平方向的调整一个图片,或许要这样做:

.box > img { width: 100%; }

垂直方向的时候:

.box > img { height: 100%; }

For other boxes we use percentage for margins to position them against the parent block. If we need an explicit offset we use calc expression:
对于一些使用百分比的盒模型用外边距去定位它们很有可能会把父元素的块撑开,如果我们需要明确的低效我们可以使用calc表达式:

.box {
  width: calc(100% - 40px);
}

When we have a grid we set column widths in percentage also. It may bring to a question if you need some spacing between columns. You can go again with calc(25% - gap width), but I prefer to usetransparent background instead, which is inside box model and doesn’t require box re-sizing.
The trick is you need to prevent background to extend underneath box border.
当使用网格布局的时候实际上也会给每个列设置一个百分比的宽度,如果我们需要列与列之间的空隙的时候可能会带来一些问题。 可以再次使用clac表达式,但是我更喜欢用透明的背景替代这种方式,这样内部的元素不需要重新定型,技巧是你需要防止背景扩展底下的盒子的边框。

background-clip: padding-box; // background extends on padding, but not on border

If you need the columns of the same height without using table, it may appear challenging. In fact the issue can be usually solved as easy as that:
如果你需要几个列都是一样高的,而且不使用表格,这个需求可能激发你的挑战欲,事实上这个问题通常可以这样简单的解决:

.item {
    margin-bottom: -99999px;
    padding-bottom: 99999px;
}

居中一个大小未知的盒子 Centering a box of unknown size

In RWD the elements sizes are mostly relative. It makes tricky to position children elements. Well, if you know exact static size of child element you can do position:absolute, left/top in percents and adjust to the desired position with negative margin. But often we don’t know the box size. We can
go, of course, with table-cell and suffer its quirks. A better choice would be to leverage vertical-align property available for inline-block elements. Its behavior is also not very obvious. If you simply set vertical-align to middle on parent element, the child element doesn’t shift to the center. There
must be some magic involved:
在响应式web设计中,元素的大小尺寸通常都是相对的。这样在定位一个字元素的就是就显得有些棘手了。如果你知道子元素的尺寸是静态的你可以使用绝对定位,使用百分比规定left和top,并且可以用负的外边距来调整他们的位置。但是通常情况下我们是不知道盒子的尺寸的, 当然可以继续,使用table-cell并忍受
它的怪异模式的蹂躏。 好的选择是利用 vertical-align property available for inline-block elements. 垂直对齐的属性适用于inline-block的元素。这种行为也不是非常的明显。 如果你直接简单的设置垂直对齐的方式在元素的父节点上,子元素通常不会按照你设置的方式对齐。
这里有一些略为神奇的方案:

.container {
  text-align: center;
  font-size: 0;
}

.container:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-right: -0.25em; /* Adjusts for spacing */
}

.content {
  display: inline-block;
  vertical-align: middle;
  width: 300px;
}

In some cases that is the best option available but, in general, before choosing a proper centering approach you rather consult to Centering in CSS: A Complete Guide.
很多例子中这就是最适合的选择,但是在选择一个正派的居中的手段你应该参考一下 CSS居中完全手册。
像HTML5那样做 Going HTML5 way

There were times when we used tables to layout the page, now we go mostly with floats. However when it comes to RWD (responsive web design) we need hacks over hacks. In fact in modern browsers we have special tools such as CSS Flexible Box Module,CSS Grid Layout Module, CSS Regions Module, CSS Multi-column Layout Module. The problem is that not all the modules already widely supported. But if you can sacrifice support for as old browsers as a collection of layout examples solved with Flexbox.

距离我们使用表格布局已经有些年代了,现在用的大多数是浮动的方式多一些。 然而这些年响应式的设计出现之后我们需要hack再hack,心好累。实际上所有现代的浏览器都有支持了新的工具比如像弹性 Flexbie Box模式, CSS网格布局模型,CSS区域模型,CSS多列布局模型。问题是并不是所有的这些
新特性都被广泛的支持了。但是你可以牺牲旧浏览器的支持像 用Flexbox 解决问题的布局例子集合。
延伸阅读 Further Reading

* [A Complete Guide to Flexbox](http://css-tricks.com/snippets/css/a-guide-to-flexbox/)

8. 用CSS制作简单的形状 Make simple graphic shapes with CSS

When you need a simple shape on a page you can use an image and it means an addition HTTP request except it is a previously loaded sprite or embedded Base64. You can go with embedded SVG or you can make a shape out of a generic HTML element with CSS.
If you need a circle or oval you may do with border-radius on a block element as easy as it:

当你页面中需要一个简单的形状的时候你可以用图片,但是它意味着会多一个http请求,或者需要用雪碧图或者用内嵌的base64编码。你也可以使用嵌入的SVG代码或者你也能够用CSS和HTML制作需要的图形。

制作圆圈:

.circle {
  width: 10rem;
  heigh: 10rem;
  border-radius: 50%; 
  background-color: red;
}

制作箭头:

.arrow {
  width: 0;
  height: 0;
  border-top: 2rem solid red;
  border-left: 2rem solid transparent;
  border-right: 2rem solid transparent;
  border-bottom: 2rem solid transparent;
}
.arrow:hover {
border-top: 2rem solid transparent;
border-bottom: 2rem solid red;
}

If we bring a little of animation, we can get really fancy stuff. Check this Burger Menu out. It became a UX trend.
如果再加一点动画,我们可以做非常花哨的效果,看这个menu ,它就是个用户体验的趋势。
By using pseudo-elements :after, :before, multiple backgrounds (CSS3 Patterns Gallery) we can achieve unbelievable complex drawings. Just take a look at this collection A Single Div: a CSS drawing project. Mind that all these pictures are made of a single div.
I’m not saying that CSS drawings are to replace binary image files or SVG, but these techniques are something you rather keep in mind.
使用伪元素,结合CSS3多背景,我们可以做到很多不可思议的复杂图形。 看着这个集合 单一div绘制的图形 ,要知道这些图形可是仅仅用了一个div绘制出来的。我不是说CSS绘图可以替代二进制图片或者SVG,只是提醒这样的技术应该铭记于心。

9.不用JavaScript实现通用的用户交互体验 (Achieve generic UX interactions without JavaScript)

You probably know that some interactions on the front-end can be achieved with CSS only. Considering CSS is no programming language, a mini-app such as a game written on it looks like impossible magic. In fact the principles behind CSS control on user iterations are not hard to grasp.
:hover
It the old days we needed JavaScript to power drop-down menus. Now we rely on :hover pseudo selector:

你可能知道前端的一些交互可能只用通过CSS就可以实现, 考虑到CSS不是一个编程语言,一个小的app像游戏类似的能够用CSS写出来似乎不可能的神奇。实际上这些隐藏在CSS后的控制用户的原理不难掌握。
很久以前我们用JavaScript的力量来控制下拉惨淡,现在我们可以依赖:hover伪选择器:

<li class="item">
  Item
  <nav class="subnav">nav>
li>

.subnav {
  display: none;
}
.item:hover .subnav {
  display: block;
}

Checkbox-hack (:checked)

When we click on a label element that associated to an input of type checkbox, the input changes its state (checked or no). The state is available in CSS as :checked pseudo selector.

当我们点击与checkbox关联的label的时候,这个input就会改变它的状态,这样的装载在CSS的伪选择器中也是适用的,所以基于它可以实现很多效果,例如:

id="btn1" type="checkbox" class="vbtn-state" />

<div class="vbtn-view">
  expandable content
div>

.vbtn-state {
  position: absolute;
  top: -9999px;
  left: -9999px;
  /* For mobile, it's typically better to position checkbox on top of clickable
    area and turn opacity to 0 instead. */
}
.vbtn-trigger {
  cursor: pointer; 
}
.vbtn-view {
  display: none;
}
.vbtn-state:checked + .vbtn-trigger + .vbtn-view {
  display: inline-block;
}

跟前面的一篇CSS选项卡切换的原理一毛一样,就不必多说什么了。
用这个原理都可以做哪些东西 Look at all the stuff you can do with the “Checkbox Hack”

target

:target pseudo-selector is matched if element is referred by fragment identifier in URI. In other words if we have a URI site.com/#some requested the styles of #some:target selector will be matched.
:target伪选择器可以匹配相关的URL片段标识符,换句话说如果有个URL是这样的site.com/#some 那么样式#some:target选择器将会匹配它。

<span id="about" class="target">

span>
<div class="modal">
  expandable
  <a href="#">Close thisa>
div>
<a href="#about">Click herea>

In CSS we just need to use a sibling combinator to specify which sibling we what to show up. Note that the target element we set into fixed position. That is to avoid “jumping” within open document.
在CSS中我们只需要配合相邻的连接符就可以指定我们想展示的元素。 注意这个target元素我们设置了fixed定位,这样会避免在打开的时候页面跳动。

.target {
  display: block;
  left: 0;
  position: fixed;
  top: 0;
  width: 0;
  height: 0;
  visibility: hidden;
  pointer-events: none;
}
.modal {
  display: none;
}
.target:target + .modal {
    display: block;
}

You can find an example of modal window using :target at Fancy Modal Windows without JavaScript
你可以作出样式的对话框的窗口例子:Fancy Modal Windows without JavaScript

:focus, :active

Closest alternative to a ‘click’ event handler in CSS is the :active or :focus pseudo class selectors. Here we need to remember that the first selector ceases to match once the mouse-button is released. The the second selector ceases to match once the given element is no longer focused. Yet it can be used still, see 4 Methods CSS3 Tabbed Content

You may think now why to bother with CSS tricks while this functionality is easy achievable with JavaScript. Besides CSS implementation is always faster, we shall not forget about progressive enhancement. If you made menu, expandables, tabs and modals with CSS, you deliver the core user experience before JavaScript is loaded and even when it’s, by some reason, wasn’t loaded at all.
CSS中最接近点击事件的是:active或:focus的伪选择器,这里需要记住当鼠标按钮释放的时候第一个选择器的匹配就释放了,第二个选择器会一直匹配直到给定的元素不再拥有焦点。当然它还能被用。4 Methods CSS3 Tabbed Content
你可能会想CSS的招数这么麻烦干嘛要使用它,这个效果用JavaScript可以很容易的实现。除此之外CSS实施总是块,我们不应该忘记渐进增强。如果你用CSS制作菜单,tab或者modals.你可以在javaScript加载之前提供核心的用户体验,或者出于某种原因他不加载。

10. 用相对的单元设置字体排版 Set typography sizes in relative units

You have may noted that sound projects usually have font sizes set in relative units (e.g. em). That gives addition flexibility. You can scale fonts across the entire document by changing base font size e.g. via media query. Unfortunately it comes at a cost. The deeper cascade the harder sizes in ems to maintain. Modern browsers support rem units, that relative not to the parent, but to the base font size. So we can set base font size as 62.5%. That gives us translation px to rem as easy as 14px /10 = 1.4rem. However while doing RWD we need would like to scale not only globally but in scope of a component (see Component-based CSS chapter). So we set components base font size in rems and component inner elements typography relative to it in ems.
你可能注意到那些比较该的项目通常使用相对的字体单位(em),这样能够增加灵活性。 你可以通过改变基础字体大小来缩放整个文档的字体。例如媒体查询,很不幸,他是有代价的。更深层次的练级em在很难维护。主流的浏览器开始支持rem单位,这个是不和相关的父元素相关,而是和基础的字体大小相关。 这样我们可以设置基础的字体大小是62.5%.这样给了我们转化px到rem的便利性。然而在响应式开发中我们需要不仅在全局中缩放而且可以在局部的组件中缩放。 所以在组件测年用rem单位,在组件内部的元素排版用em单位。

/* Global scope */
html {
  font-size: 62.5%; // 10px
}
@media (max-width: 960px) {
  html {
    font-size: 56.25%; //9px
  }
}

/* Components */
.header {
  font-size: 1.6rem;
}
.footer {
  font-size: 1rem;
}
.sidebar {
  font-size: 1.4rem;
}

/* scale with components */
h1 {
  font-size: 2em;
}
h2 {
  font-size: 1.4em;
}
h3 {
  font-size: 1.2em;
}

Modern browser support a wide range of other units. I personally found useful viewport percentage lengths such as vw. It is relative not to base font size, but to viewport width itself and scales with document view resizing simultaneously.
现代浏览器支持的单位范围更广。我个人发现了非常有用的根据视窗百分比宽度的vw。 它相关的不是基础字体而是视窗宽度,视窗宽度所当的时候文档的视区也会同时改变大小。

延伸阅读 (Further Reading)

* [Font Size Idea: px at the Root, rem for Components, em for Text Elements](https://css-tricks.com/rems-ems/)

编后记 (Afterword)
I collected here 10 aspects that I found important. Of course it cannot cover everything what developer shall take care of. My intend was to bring attention to the fact that CSS is fat more complex thing that it may seem and must be taken as seriously as any other declarative or imperative language.
我收集了10个自己发现很重要的方面,当然不能够涵盖开发者应该注意的所有东西,我的意图是让CSS引起注意,注意到它的足够的复杂,复杂到应该像其他的声明试的或者命令试的语言一样认真地对待。

ps: 安利下作者(Sheiko) 的博客 http://dsheiko.com/aboutme,毕竟未经同意擅自翻译。希望这篇文字对写出好的CSS代码有启发有帮助。

你可能感兴趣的:(CSS/CSS3)