作为一个前端,毫无疑问css肯定是最基本的一项妙技之一。css是一个标记言语,没有编程言语的诸多特征,比方变量定义,复用,嵌套等,所以响应的开辟效力也受到限制。
在寻求效力和自动化的当下,涌现了一批处置惩罚计划,像是css预编译言语Less, Sass等,处置惩罚css定名争执的css-modules,react中css的最好实践styled-components等。
本篇文章不在于议论css的技能进修,而在于议论css的这些提拔开辟效力的计划。
Less
Less, Sass, Stylus等 css预编译言语
,给css给予了编程特征。拿 Less
来讲,它扩大了 CSS 言语,增加了变量、Extend、Mixin、函数等特征,也支撑import导入文件,使 CSS 更容易保护和扩大。本篇简朴引见一下Less的一些特征,细致的教程能够上Less官网检察。
怎样运用Less?
我们能够在 敕令行
直接运用less,也能够经由过程 node api
去运用less,或许经由过程 webpack
,gulp
,grunt
等的 less插件
去运用,以至能够在浏览器端运用,异常天真。这里简朴说一下在敕令行中运用less。
$ npm i less -g
# 当less被装置以后,就可以够运用全局敕令lessc
$ lessc bootstrap.less bootstrap.css
一、变量
变量使css代码更容易保护。
比方有个主色 #ef8376
,在全部款式表中,我们有多处运用这个色彩。假如主色更改的话,比方主色要变成 #000
,我们就要手动去全局替代这个变量,而有一些 #ef8376
我们却不愿望替代掉,如许就形成了极大的搅扰。
假如我们运用less的话,就可以够这么写:
@primaryColor: #ef8376;
.banner {
background-color: @primaryColor;
.text {
color: @primaryColor;
border-color: #ef8376;
}
}
我们要修正主色,只须要将 @primaryColor
修正为 ‘#000’即可。
二、Extend
Extend让我们能够用伪类的写法去兼并一些类
。
比方:
nav ul {
&:extend(.inline);
background: blue;
}
.inline {
color: red;
}
会编译成:
nav ul {
background: blue;
}
.inline,
nav ul {
color: red;
}
三、Mixin
Mixin既有Extend继续已有类的特征,也有其他高等的特征,比方支撑变量,支撑像运用要领一样运用mixin
支撑变量
.foo (@bg, @color: '#000') {
background: @bg;
color: @color;
}
.unimportant {
.foo(#f5f5f5);
}
.important {
.foo(#121212) !important;
}
会编译成:
.unimportant {
background: #f5f5f5;
color: #000;
}
.important {
background: #121212 !important;
color: #000 !important;
}
像要领一样运用Mixin
.count(@x, @y) {
@margin: ((@x + @y) / 2);
@padding: ((@x + @y) / 4)
}
div {
margin: .count(16px, 16px)[@margin];
padding: .count(16px, 16px)[@padding];
}
.loop(@counter) when (@counter > 0) {
.loop((@counter - 1)); // next iteration
width: (10px * @counter); // code for each iteration
}
.text {
.loop(5); // launch the loop
}
会编译成:
div {
margin: 16px;
padding: 8px;
}
.text {
width: 10px;
width: 20px;
width: 30px;
width: 40px;
width: 50px;
}
四、Import导入文件
// head.less
.banner {
background-color: red;
}
// footer.css
.footer {
background-color: green;
}
@import './head.less';
@import css './footer.css';
会编译成:
.banner {
background-color: red;
}
.footer {
background-color: green;
}
五、要领
Less支撑一些经常使用的辅佐要领
比方darken
和lighten
用来加深或淡化色彩。
body {
background-color: darken(hsl(90, 80%, 50%), 20%);
color: lighten(hsl(90, 80%, 50%), 20%);
}
会编译成:
body {
background-color: #4d8a0f;
color: #b3f075;
}
css-modules
css-modules 相较于 Less 来讲有所差别,css-modules 只是拓展了 css 的写法,处置惩罚了css的块作用域和全局作用域,而不是将css变成一门编程言语。
为何须要 css-modules?
Css一直以来都有一个题目,就是css定义的类都是全局的,我们虽然能够经由过程差别的定名空间或是加前缀的体式格局去防止类的殽杂和争执,然则在写法上却不是那末的干净利落,而且一旦重构css的话,也会形成很大的搅扰。
为了让我们能随便的写类名而不须要斟酌争执或是掩盖,css-modules 便涌现了。
css-modules供应了 块作用域 :local
和 全局作用域 :global
,这两个特征就可以很好的防止css的定名争执。
怎样运用?
起首来讲一下怎样运用 css-modules。
当我们在运用webpack的时刻,最简朴的用法是经由过程 css-loader 来开启对 css-modules 的支撑。以下:
{
test: /\.css$/,
use: [
{
loader: 'css-loader',
options: {
modules: true, // 开启对css-modules的支撑
localIdentName: '[name]__[local]___[hash:base64:5]' // 天生的类名的花样
}
}
]
}
同时能够合营less-loader 和 postcss运用。注重:在连系less-loader的时刻能够涌现对url的兼容题目。见:https://github.com/webpack-co… 。而且 less-loader 的保护者以为连系 less-loader 和 css-modules没什么必要。。
- css-loader – webpack开启css modules
- postcss-modules – postcss的 css-modules 插件
一、作用域
css-modules供应了两个关键字,:local
和 :global
。
比方这类写法:
// App.css
:local(.banner) {
background: red;
}
:local(.banner .text) {
color: yellow;
}
.center {
color: green;
}
:global(.global-class-name) {
color: blue;
}
会编译成:
.App__banner___3NbRo {
background: red;
}
.App__banner___3NbRo .App__text___2j1Ht {
color: yellow;
}
.App__center___3eDJo {
background: green;
}
.global-class-name {
color: blue;
}
:global
声明的类不会被编译,会坚持稳定。
同时,我们在js中引入css,写法以下:
/**
* styles是什么呢?styles实际上是一个经由处置惩罚过的类名的鸠合。
*
* 比方上边这个css文件,处置惩罚后的style对象是如许的:
*
* {
* banner: 'App__banner___3NbRo',
* text: 'App__banner___3NbRo App__text___2j1Ht',
* center: 'App__center___3eDJo'
* }
*
* 如许我们就可以够明白为何css-modules能够防止明显争执了。
* 定名都依据我们设置的hash划定规矩重写了,保证了类名的唯一,而且在天生的html构造里也举行了替代,还何来争执?
*/
import styles from './App.css';
import React from 'react';
const html = () => {
return <div class={styles.banner}>
<span class={style.text}>HAHAHAHHAHAHA</span>
</div>;
};
export default html;
二、Composition – 夹杂构成
css-modules支撑多个类的夹杂构成。比方:
.colorRed {
color: red
}
.text {
composes: colorRed;
background: #000;
}
会编译成:
.App__colorRed___yoG_f {
color: red
}
.App__text___2j1Ht {
background: #000;
}
能够看到,天生的css中并没有任何的变化,那这个composes做了什么呢?实在在经由过程js援用的对象内发生了变化。以下:
{
"colorRed": "App__colorRed___yoG_f",
"text": "App__text___2j1Ht App__colorRed___yoG_f"
}
那末在经由过程 styles.text
运用 text
类的时刻,实在也同时运用了 colorRed
类,达到了夹杂构成的结果。
三、Import – 援用
css-modules
支撑援用其他文件的类。
比方:
// green.css
.green {
color: green;
}
// text.css
.text {
background-color: red;
composes: green from './green.css';
}
会编译成:
.green__green___1v20L {
color: green;
}
.text__text__2jfs0 {
background-color: red;
}
实在跟 二
一样,天生的css并没有什么修改,实在转变的是天生js对象的内容:
import styles from './text.css';
// styles = {green: 'green__green___1v20L', text: 'text__text__2jfs0 green__green___1v20L'}
styled-components
styled-components, 多是React中css的最好实践了,假如你喜好,你也能够叫它styled-react-components
: )。设想一下,像写react组件一样去写css,是一种什么样的体验?
以下,你能够如许来写款式:
import React from 'react';
import styled from 'styled-components';
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
export default () => <Wrapper>
<Title>Hello World, this is my first styled component!</Title>
</Wrapper>;
styled-components
会自动帮你在 运转时
天生一个款式表,插进去到 <head>
下的 <style>
标签中,比方上边的代码,会在运转是天生以下代码:
<head>
<style data-styled-components>
/* sc-component-id: model__Title-cooNNd */
.model__Title-cooNNd {} .jHitSF{font-size:1.5em;text-align:center;color:palevioletred;}
/* sc-component-id: model__Wrapper-bEJrHK */
.model__Wrapper-bEJrHK {} .ipFfju{padding:4em;background:papayawhip;}
</style>
</head>
<body>
<section class="model__Wrapper-bEJrHK ipFfju">
<h1 class="model__Title-cooNNd jHitSF">Hello World, this is my first styled component!</h1>
</section>
</body>
我们能够看到,我们在js中写的款式,被插进去到了 <style>
中,而且天生了一个随机的类名,而且这个类名,也是被 react-dom
天生的DOM构造所援用。
受益于 styled-components
,我们贯彻了 react
的 万物皆组件
的头脑,使我们在css的组件化上又推进了一步(宣布一个纯css组件尝尝?) : )
在这篇文章里,我会简朴议论一下 style-components
的用法和特征。
怎样运用?
styled-components
平常合营着 react
运用,固然也支撑 vue
(vue-styled-components)。抛开这两个来讲,你也能够直接在原生js下运用:
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
我们这里讲合营 react
的用法。
一、起首,装置依靠
$ npm i styled-components
# 合营着babel来运用
$ npm i -D babel-plugin-styled-components
二、设置 .babelrc
(固然,我们须要装置 webpack
,设置webpack的config,而且须要须要装置 babel-preset-env
和 babel-preset-react
,这里不赘述)
{
"presets": ["env", "react"],
"plugins": ["styled-components"]
}
经由以上简朴的设置以后,就可以够在项目中运用 styled-components
了。
东西
固然,如今的 styled-components
也是支撑了 stylelint 和 jest,所以,你也不必忧郁款式搜检和测试了 :)
下边儿说一下 styled-components
的一些用法和特征。 官方文档在这儿: https://www.styled-components…
一、动态款式赋值
你能够传props给组件,让组件依据所传的props的值动态转变款式。
const Button = styled.button`
/* 依据props的值动态转变款式的值 */
background: ${props => props.primary ? 'palevioletred' : 'white'};
color: ${props => props.primary ? 'white' : 'palevioletred'};
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
二、款式继续
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// 建立一个新Button组件,继续自Button,并对Button举行款式增加和掩盖
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
三、组件标签替代
比方,你建立了一个Button组件,你想把button
标签变成a
标签,然则款式照样button
的款式。那末你能够经由过程 withComponent
要领轻松做到。
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// 把<button>标签替代成<a>标签
const Link = Button.withComponent('a')
// 继续Link组件
const TomatoLink = styled(Link)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<Link>Normal Link</Link>
<TomatoLink>Tomato Link</TomatoLink>
</div>
);
四、动画
// 这个keyframe会随机天生一个name
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const Rotate = styled.div`
display: inline-block;
animation: ${rotate360} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;
render(
<Rotate>< 💅 ></Rotate>
);
五、Media Query
const Content = styled.div`
background: papayawhip;
height: 3em;
width: 3em;
@media (max-width: 700px) {
background: palevioletred;
}
`;
render(
<Content />
);
六、嵌套写法
styled-components
支撑嵌套写法,这个特征是从 Sass
移植过来的。
const EqualDivider = styled.div`
display: flex;
margin: 0.5rem;
padding: 1rem;
background: papayawhip;
${props => props.vertical && 'flex-direction: column;'}
> * {
flex: 1;
&:not(:first-child) {
${props => props.vertical ? 'margin-top' : 'margin-left'}: 1rem;
}
}
`;
const Child = styled.div`
padding: 0.25rem 0.5rem;
background: palevioletred;
`;
render(
<div>
<EqualDivider>
<Child>First</Child>
<Child>Second</Child>
<Child>Third</Child>
</EqualDivider>
<EqualDivider vertical>
<Child>First</Child>
<Child>Second</Child>
<Child>Third</Child>
</EqualDivider>
</div>
);
七、合营其他css类库运用
比方你在项目中引入了 bootstrap.css
,应当怎样和bootstrap
中的类合营运用呢?
const Button = styled.button.attrs({
// 天生的classList中会包括small
className: 'small'
})`
background: black;
`;
render(
<div>
<Button>Styled Components</Button>
<Button>The new way to style components!</Button>
</div>
);
八、优先级
怎样掩盖高优先级的款式呢?固然我们能够经由过程 !important
来做,不过 styled-components
更引荐下边这类做法:
const MyStyledComponent = styled(AlreadyStyledComponent)`
&&& {
color: palevioletred;
font-weight: bold;
}
`;
每一个 &
替代为天生的类,那末天生的CSS是如许的:
.MyStyledComponent-asdf123.MyStyledComponent-asdf123.MyStyledComponent-asdf123 {
color: palevioletred;
font-weight: bold;
}
那末怎样掩盖内联款式呢?以下:
const MyStyledComponent = styled(InlineStyledComponent)`
&[style] {
font-size: 12px !important;
color: blue !important;
}
`;
styled-components
推翻了传统的款式写法,像写组件一样写css,合营 react
适可而止 :)
至于在 Less、css-modules 和 styled-components 中究竟挑选哪个,就要看你的运用场景和需求了。
本章完
我的Github:
https://github.com/PengJiyuan