# 不要随便定义基础规则

少部分元素,我们认为它们职责单一,并且不会改变,所以我们把它们定义在基础规则中。不过,虽说如此,但是当我们给一个元素定义基础规则的时候,我们还是得考虑未来元素的变化会不会导致我们的工作变得复杂。

那么怎样的元素会导致这种潜在问题呢?buttontableinput元素应该是我见过最常发生的元素。让我们来深入研究一个经常会在项目中出现的例子。

# 表格

表格布局作为web页面的标准布局方式的时代早已远去。所以在项目中我们已经不需要使用表格了。

但是呢,突然有一天我们需要一个数据比较表格来显示一组特定的数据,这是第一个用到表格的地方,也是唯一需要用到表格的地方。这个数据比较表格有固定的留白,列对齐方式以及边框。

/* 表格样式 */
table {
    width: 100%;
    border: 1px solid #000;
    border-width: 1px 0;
    border-collapse: collapse;
}

td {
    border: 1px solid #666;
    border-width: 1px 0;
}

td:nth-child(2n) {
    background-color: #EEE;
}

几天,几星期或者是几个月以后,我们突然需要添加另外一个表格。这次呢,我们使用表格的目的截然不同。头部在左侧,数据在右侧,并且去除了边框,背景也改变了。通常情况下,我们会对默认样式进行覆盖。

/* 覆盖之前的样式 */
table.info {
    border-width: 0;
}

td.info {
    border-width: 0;
}

td.info:nth-child(2n) {
    background-color: transparent;
}

.info > tr > th {
    text-align: left;
}

.info > tr > td {
    text-align: right; 
}

这个方法的问题在于覆盖了基础样式。基础样式一般用于显示默认的样式,我们需要在特定的模块对它们进行修改。而数据比较表格是一个模块,它有特殊的用途,并且有定制的设计,所以即使使用的元素是唯一的,我们也不能将其放在基础样式中。

解决方法也很简单:定义一个模块。

/* 创建一个模块来替换它 */
table {
    width: 100%;
    border-collapse: collapse;
}

.comparison {
    border: 1px solid #000;
    border-width: 1px 0;
}

.comparison > tr > td {
    border: 1px solid #666;
    border-width: 1px 0;
}

.comparison > tr > td:nth-child(2n) {
    background-color: #EEE;
}

.info > tr > th {
    text-align: left; 
}

.info > tr > td {
    text-align: right; 
}

表格元素仍然有一个基础样式的设置,它总是需要100%填充它的容器,并且需要使用border-collapse: collapse

现在我们的comparison模块应该是独立的。我使用了孩子选择器来使得规则的影响尽可能地小,这样,即使我在表格当中嵌套一个表格(通常避免这样做),比较模块也不会对嵌在其中的表格产生影响。而我们的info模块只有简单的两条规则。

总的来说,我们使用了更少的CSS达成了我们想要的效果,与此同时我们还保证了我们代码整洁。双赢!!

就像之前提到的,buttoninput元素往往会和table遇到相同的问题。如果样式需要应用于一个特定的元素,那就创建一个模块,这样可以避免样式覆盖或是重写旧代码。