css!important
by Muna Mohamed
通过穆纳·穆罕默德(Muna Mohamed)
如何解决CSS特殊性问题以及何时使用!important关键字 (How to tackle CSS specificity issues and when to use the !important keyword)
案例研究 (A Case Study)
Recently, there was a Twitter poll floating around where the user asked their followers a question about CSS specificity . Unfortunately, I was unable to find the original tweet (comment below if you happen to find it!) but long story short, the majority of people got the answer wrong.
最近,有一个Twitter民意调查在用户附近向用户询问有关CSS特殊性的问题。 不幸的是,我无法找到原始推文(如果发现它,请在下面评论!),但长话短说,大多数人都给出了错误的答案。
That Twitter poll (and its aftermath) led to me brushing up on my own knowledge of the topic of specificity and in turn, made me start fixing specificity issues in my own projects — which brings me to the purpose of this post.
Twitter的民意测验(及其后果)使我重新审视了自己对特异性主题的认识,从而使我开始在自己的项目中解决特异性问题,这使我明白了这篇文章的目的。
In this post, we will be refactoring CSS code from a project of mine that has CSS specificity issues that are in need of fixing.
在这篇文章中,我们将从一个我的项目中重构CSS代码,该项目存在需要修复CSS特殊性问题。
CSS特异性 (CSS Specificity)
定义 (Definition)
Specificity is described by MDN Web Docs as:
MDN Web文档将特异性描述为:
the means by which browsers decide which CSS property values are the most relevant to an element and therefore, applied.
浏览器确定哪些CSS属性值与元素最相关并因此被应用的方法。
规则 (Rules)
When deciding which CSS property values are the most relevant to apply to an element, the browser uses the source order (i.e the cascade) of the CSS stylesheet to determine this. But this rule applies when the CSS selectors have equal specificity. What happens when the specificity of one CSS selector is higher than another?
在确定哪些CSS属性值与元素最相关时,浏览器使用CSS样式表的源顺序(即级联)来确定。 但是,当CSS选择器具有相同的特异性时,该规则适用。 当一个CSS选择器的特异性高于另一个时,会发生什么?
In that case, browsers will use the specificity of a CSS selector to determine what CSS statements to apply. The higher the specificity of a CSS selector, the more likely that browsers will apply its CSS declarations over another.
在这种情况下,浏览器将使用CSS选择器的特殊性来确定要应用CSS语句。 CSS选择器的特异性越高,浏览器就越有可能将其CSS声明应用于另一个。
nav a {
color: green;
}
a {
color: red;
}
For example, in the example above, both of the CSS selectors are targeting the same HTML element, the anchor tag. In order to determine which CSS rule to apply to the anchor tag, the browser will calculate the specificity value and check which one is the highest. In this case, the first selector has a higher specificity value, therefore the browser will use its declarations to apply to the anchor tag.
例如,在上面的示例中,两个CSS选择器都针对同一HTML元素(锚标记)。 为了确定要应用于锚标记CSS规则,浏览器将计算出特异性值并检查哪一个是最高的。 在这种情况下,第一个选择器具有更高的特异性值,因此浏览器将使用其声明将其应用于锚标记。
I’d like to point out here that although !important is not a CSS selector, it is a keyword that is used to forcefully override a CSS rule regardless of the specificity value, origin or source order of a CSS selector. Some use cases include:
我想在这里指出,尽管!important不是CSS选择器,但它是一个关键字,用于强制覆盖CSS规则,而与CSS选择器的特异性值,来源或源顺序无关。 一些用例包括:
- Temporary fixes (a bit like putting duct-tape on a leaky pipe) 临时修复(有点像将胶带绑在泄漏的管道上)
- Overriding inline styling 覆盖内联样式
- Testing/debugging purposes 测试/调试目的
As useful as using the !important keyword may seem, the use of it can be more problematic than helpful. Over time, it can make it difficult to maintain your CSS and it can negatively affect the readability of your stylesheet, particularly for anyone else who is or will be working with it in the future.
尽管使用!important关键字似乎很有用,但使用它可能会比没有帮助更成问题。 随着时间的流逝,它可能会使您CSS难以维护,并且可能会对样式表的可读性产生负面影响,尤其是对于将来将要使用或将要使用它的任何人。
Which brings us to what we’ll be doing today — fixing the specificity issues in a project.
这使我们进入了今天要做的事情-解决了项目中的特殊性问题。
该项目 (The Project)
A little background about the project we’ll be refactoring — it is a Netflix inspired landing page using MovieDB’s API.
关于我们将要重构的项目的一些背景知识-它是使用MovieDB API的,受Netflix启发的登录页面。
样式表 (The stylesheet)
The aim is to remove the “!important” keyword from the CSS rules that it has been applied to by refactoring the code so that it follows specificity rules.
目的是通过重构代码以使其遵循特定性规则,从而从已应用CSS规则中删除“!important”关键字。
Below, you can see the stylesheet for the project.
在下面,您可以看到该项目的样式表。
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
body {
margin: 0;
padding: 0;
overflow-x: hidden;
}
.wrapper {
width: 100%;
}
.wrapper #header {
position: fixed;
z-index: 300;
padding: 15px;
width: calc(100% - 30px);
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(to bottom, black 0%, transparent 100%);
}
.wrapper #header #brand-logo {
color: #d32f2f;
text-shadow: 1px 1px 2px black;
letter-spacing: 5px;
text-transform: uppercase;
font-family: Montserrat;
font-weight: bold;
font-size: 22px;
}
.wrapper #header #menu-icon {
display: none;
}
.wrapper #header .nav-link,
.wrapper #header .icon {
color: #bdbdbd;
cursor: pointer;
}
.wrapper #header .nav-menu {
width: 400px;
display: flex;
justify-content: space-around;
align-items: center;
}
.wrapper #header .nav-link {
padding: 5px 10px;
font-size: 15px;
font-family: century gothic;
text-decoration: none;
transition: background-color 0.2s ease-in;
}
.wrapper #header .nav-link:hover {
color: #c62828;
background-color: rgba(0, 0, 0, 0.7);
}
.wrapper #header .icon {
font-size: 16px;
}
.wrapper #header .icon:hover {
color: #c62828;
}
.wrapper #site-banner,
.wrapper #categories {
width: 100%;
}
.wrapper #site-banner {
height: 550px;
background-image: url("https://s1.gifyu.com/images/rampage_2018-1024x576.jpg");
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
}
.wrapper #site-banner .main-movie-title,
.wrapper #site-banner .watch-btn,
.wrapper #site-banner .main-overview {
position: absolute;
z-index: 3;
}
.wrapper #site-banner .main-movie-title, .wrapper #site-banner .watch-btn {
text-transform: uppercase;
}
.wrapper #site-banner .main-movie-title {
top: 120px;
left: 20px;
background: -webkit-linear-gradient(#ff9100, #dd2c00);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 55px;
font-family: Montserrat;
font-weight: bold;
}
.wrapper #site-banner .main-overview {
width: 400px;
top: 230px;
left: 25px;
color: #fafafa;
line-height: 25px;
font-family: helvetica;
}
.wrapper #site-banner .watch-btn {
width: 150px;
height: 35px;
top: 350px;
left: 25px;
border: none;
border-radius: 20px;
color: #fafafa;
cursor: pointer;
transition: all 0.2s ease-in;
background-color: #ff0000;
box-shadow: 1px 5px 15px #940000;
}
.wrapper #site-banner .watch-btn:hover {
color: #F5F5F5;
background-color: #940000;
}
.wrapper .after {
position: relative;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}
.wrapper #categories {
padding: 30px 0;
display: flex;
flex-direction: column;
background: linear-gradient(to top, #090909 0%, #000000 100%);
overflow: hidden;
}
.wrapper #categories .category {
margin: 30px 0;
}
.wrapper #categories .category-header, .wrapper #categories .content {
margin-left: 20px;
color: #B0BEC5;
font-family: helvetica;
}
.wrapper #categories .category-header {
margin-bottom: 50px;
font-weight: normal;
letter-spacing: 5px;
}
.wrapper #categories .content {
position: relative;
right: 0;
display: flex;
justify-content: flex-start;
transition: all 3s ease-in-out;
}
.wrapper #categories .movie {
margin-right: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
.wrapper #categories .movie-img {
transition: all 0.2s ease-in;
}
.wrapper #categories .movie-img:hover {
-webkit-filter: contrast(1.1);
filter: contrast(1.1);
-webkit-transform: scale(1.05);
transform: scale(1.05);
cursor: pointer;
}
.wrapper #footer {
width: 100%;
height: 120px;
background-color: #090909;
display: flex;
align-items: flex-end;
justify-content: flex-start;
}
.wrapper #footer #copyright-label {
margin-left: 20px;
padding: 10px;
color: rgba(255, 255, 255, 0.3);
opacity: 0.7;
letter-spacing: 2px;
font-family: helvetica;
font-size: 12px;
}
//Media Query
@media (max-width: 750px) {
.nav-menu {
visibility: hidden;
}
#menu-icon {
display: block !important;
font-size: 22px;
}
.main-movie-title {
font-size: 45px !important;
}
.main-overview {
width: 350px !important;
font-size: 14px !important;
}
.watch-btn {
width: 130px !important;
height: 25px !important;
font-size: 13px;
}
.movie-img {
width: 170px;
}
}
So, we can see from the stylesheet that the use of the !important keyword is mainly focused in the media query section which outlines the styles that the browser should apply when the screen-width is less than 750 pixels.
因此,我们可以从样式表中看到!important关键字的使用主要集中在媒体查询部分,该部分概述了当屏幕宽度小于750像素时浏览器应采用的样式。
So, what happens when we remove the !important keyword from the CSS rules that it has been applied to? Well, we no longer have a “trump card” forcefully overriding the CSS rules of other CSS selectors that target the same HTML element. So, the browser will look at the stylesheet to see if there are any conflicting CSS rules.
那么,当我们从CSS规则中删除!important关键字时会发生什么呢? 好了,我们不再拥有“王牌”,可以强行覆盖其他针对同一HTML元素CSS选择器CSS规则。 因此,浏览器将查看样式表以查看是否存在任何冲突CSS规则。
If there are, then in order to determine which CSS rules to apply over another, the browser will use the source order, specificity and importance of the CSS selectors. If the CSS selectors with conflicting CSS rules have equal specificity, then the browser will use the source order rule and apply the CSS rules of the CSS selector that comes lower down in the stylesheet. Using this information, we can see that this situation is not the case for our stylesheet.
如果存在,则为了确定要在另一个CSS规则上应用CSS规则,浏览器将使用CSS选择器的源顺序,特异性和重要性。 如果具有冲突CSS规则CSS选择器具有相同的特异性,则浏览器将使用源顺序规则,并应用样式表中位于下方CSS选择器CSS规则。 使用此信息,我们可以看到样式表不是这种情况。
But, if the CSS selectors with conflicting CSS rules don’t have equal specificity, then the browser will apply the CSS rules of the CSS selector that has higher specificity. We can see from our stylesheet that this is the case; the CSS selectors in our media query have lower specificity than the CSS selectors in the main part of our stylesheet.
但是,如果CSS规则冲突CSS选择器没有相同的特异性,则浏览器将应用具有更高特异性CSS选择器CSS规则。 从样式表中可以看出是这种情况。 媒体查询中CSS选择器的特异性低于样式表主要部分中CSS选择器。
Now that we have identified the issue, let’s fix it!
现在我们已经确定了问题,让我们解决它!
First we have to locate the corresponding CSS selectors that match the CSS selectors in our media query.
首先,我们必须在媒体查询中找到与CSS选择器匹配的相应CSS选择器。
.wrapper #header #menu-icon {
display: none;
}
.wrapper #site-banner .main-movie-title {
...
font-size: 55px;
...
}
.wrapper #site-banner .main-overview {
width: 400px;
...
}
.wrapper #site-banner .watch-btn {
width: 150px;
height: 35px;
...
}
@media (max-width: 750px) {
#menu-icon {
display: block !important;
...
}
.main-movie-title {
font-size: 45px !important;
}
.main-overview {
width: 350px !important;
font-size: 14px !important;
}
.watch-btn {
width: 130px !important;
height: 25px !important;
...
}
}
We can see that the CSS selectors in the main part of the stylesheet have higher specificity than the corresponding CSS selectors in the media query. Despite the CSS selectors in the media query appearing later on in the stylesheet, because of specificity rules (which take precedence over source order rules), the browser will apply the CSS rules of the CSS selectors that come before it.
我们可以看到,样式表主要部分中CSS选择器比媒体查询中相应CSS选择器具有更高的特异性。 尽管媒体查询中CSS选择器出现在样式表的后面,但由于特定性规则(优先于源顺序规则),浏览器仍将应用其前面CSS选择器CSS规则。
To fix this, we must increase the specificity values of the CSS selectors in the media query. If we make it so that the CSS selectors that target the same HTML elements have equal specificity, then the browser will follow the source order rule. The CSS rules outlined in the media query (that’s located lower down in the stylesheet) will be applied when the screen-width is less than 750 pixels.
要解决此问题,我们必须增加媒体查询中CSS选择器的特异性值。 如果我们做到了使针对相同HTML元素CSS选择器具有相同的特异性,那么浏览器将遵循源顺序规则。 当屏幕宽度小于750像素时,将应用媒体查询中概述CSS规则(位于样式表的下方)。
The end result will look like this:
最终结果将如下所示:
.wrapper #header #menu-icon {
display: none;
}
.wrapper #site-banner .main-movie-title {
...
font-size: 55px;
...
}
.wrapper #site-banner .main-overview {
width: 400px;
...
}
.wrapper #site-banner .watch-btn {
width: 150px;
height: 35px;
...
}
@media (max-width: 750px) {
.wrapper #header #menu-icon {
display: block;
...
}
.wrapper #site-banner .main-movie-title {
font-size: 45px;
}
.wrapper #site-banner .main-overview {
width: 350px;
font-size: 14px;
}
.wrapper #site-banner .watch-btn {
width: 130px;
height: 25px;
font-size: 13px;
}
}
And that’s it! We have removed all traces of the !important keyword from the stylesheet. Already we can see that the stylesheet is easier to read, and you can imagine that our refactored stylesheet would be a lot easier to work with and maintain (particularly if others will be working on it too).
就是这样! 我们从样式表中删除了!important关键字的所有痕迹。 我们已经看到样式表更易于阅读,并且您可以想象我们重构后的样式表将更易于使用和维护(尤其是如果其他人也将对其进行处理)。
结论 (Conclusion)
So, what have we learned?
所以我们学了什么?
We have learned about how browsers determine which CSS styles to apply by using the source order, specificity and origin of selectors. We have also learned about the problems which can arise by using !important in your CSS and why its use should be kept to a bare minimum.
我们已经了解了浏览器如何通过使用选择器的源顺序,特异性和来源来确定要应用CSS样式。 我们还了解了在CSS中使用!important可能引起的问题,以及为什么应尽量减少使用它。
We do not have to resort to using !important in order to fix things — there are much better solutions out there.
我们不必依靠!important来解决问题-那里有更好的解决方案。
The concept of specificity is one that can take a while to get your head around, but I hope that by documenting the process and using a real project, it helps you better understand the concept of specificity and how to apply it in your own CSS.
特异性的概念可能需要一段时间才能引起您的注意,但是我希望通过记录过程并使用一个真实的项目,它可以帮助您更好地理解特异性的概念以及如何将其应用于您自己CSS中。
Additional Resources
其他资源
You can find the project we’ve been working on here.
您可以在这里找到我们一直在努力的项目。
希望您喜欢这篇文章! 如果您这样做了,❤️,? 和分享! 直到下一次! ✌️ (I hope you enjoyed this post! If you did, ❤️, ? and share! Till next time! ✌️)
css!important