Spring Festival is coming, and another year is slipping away.

It’s the end of the year, and it’s always flooded the screen with year-end reviews. For example, state of js 2020 and state of CSS 2020 questionnaires, which are closely related to front-end developers, have issued statistical reports successively. In the summary of the latter report, tailwindcss can be said to be a sudden rise with eye-catching strength.

Today we’re talking about Tailwind and his way back.

Preface: The path of the Tailwind

In the data reported by State of CSS 2020, we can see that tailwind satisfaction is very high, and the percentage of developers who have used tailwind has increased dramatically over the past year. Tailwind could say, “Try everything you haven’t used and say yes to everything you’ve used.”

On the other hand, the CSS principle behind Tailwind, Atomic CSS, has surpassed the widely accepted BEM naming rules to become the most satisfying and popular CSS principle among developers.

Why did tailwinds come into being

Tailwind focuses on one of the most common problems in front-end development: global CSS conflicts.

Global CSS conflicts, an issue that first gained widespread attention with the emergence of SPA, led to the creation of a number of CSS principles and tools. With the advent of the microfront-end era, with new scenarios, this issue again attracts more attention.

The resulting principles and tools include:

  • BEM nomenclature, represented by BEM nomenclature, is designed to standardize CSS and reduce class name conflicts.
  • Dynamically modify class names or add attributes by intervening in the compilation process to avoid selector conflicts: CSS in JS, scoped CSS…
  • Context-isolation schemes with microfrontend: Web Components, Iframe…

The principle of CSS

To understand the philosophy behind tailwind, let’s take a quick look at a few common CSS principles.

BEM naming rules

BEM is a kind of naming convention that emerged early and has a high acceptance among developers. BEM stands for block__Element –modifier, used to avoid class name conflicts by using the module as the prefix of the namespace:

.dialog__button {}
.dialog__button--confirm {
  color: green;
}
Copy the code

BEM, an early adopter, is characterized by a simple practice that does not even require a preprocessor (typically used in conjunction with pre-processing nesting) and property selectors (perhaps even ie6 compatible at the time), but its disadvantages are also obvious: Naming is one of the eternal conundrums of software engineering, how to name modules to avoid conflicts as projects grow, and how to name classes that get too long.

ITCSS

The idea behind ITCSS is to organize CSS code into seven different levels:

  • Settings: Setting variables, etc
  • Tools: Tools to define mixins, etc
  • Generic: Generic, such as normalize code
  • Base: CSS code with labels as selectors
  • Object: Some abstract generic CSS code
  • Component: Component-level CSS code
  • -Leonard: The trumps! importantThe place where

Such as:

// settings
$yellow: #ffaa00;
// tools
@mixin sample-mixin() {}
// generic
* { box-sizing: border-box; }
// base
p { line-height: 1.5; }
// object
.o-container { display: block; }
// component
.c-btn { cursor: pointer; }
// trumps
.u-hidden { display: none!important; }
Copy the code

You can prefix the name of each layer with the name of the file name and use it with @import:

@import 'settings.color'
@import 'settings.size'

@import 'tools.gradient'

@import 'generic.normalize'

@import "elements.headings";
@import "elements.links";

@import "objects.animations";
@import "objects.layout";
@import "objects.list";

@import "components.buttons";
@import "components.dialogs";

@import "trumps.utilities";
Copy the code

In terms of naming rules for class names, BEMIT combined with BEM is recommended.

OOCSS

OOCSS (Object-oriented CSS) borrows the concepts of classes and inheritance from object-oriented programming and uses a hump name. For example, in the following example, metadata is extracted as a base class and derived from three inherited classes:

<! <p class= "metadata postMetaData" > <a> Commented on<a>21-02-2010</a> @< /p> <! Comments --> <p class= "metadata commentMetaData" > <a>Author name</a>commented on<a>21-02-2010</a>@ </p> <! -- user info --> <p class= "metadata useInfoMetaData" > <a>Author name</a>commented on<a>21-02-2010</a>@ </p>Copy the code

OOCSS focuses on semantematization of class names and common CSS extraction.

Atomic css

Atomic CSS advocates using atomized CSS classes to write code. Its ideas include:

  • Utility classes: Atomic CSS uses split toatomicGranular utility classes. For example,.text-right { text-align:: right }, a class corresponds to a single CSS.
  • Immutable CSS: Changes the class names of elements without modifying the CSS.
  • Breakpoint Prefix: Atomic CSS supports corresponding design by prefixing breakpoints with class names.

Thus, code using atomic CSS might look like this:

<div class="bg-grey text-white text-center grid-12 m:grid-6">
  hello atomic css
</div>
Copy the code

It’s hard not to look at such an idea and think, “What is neng?” The idea of. It is this counterintuitive design concept and the “if you use it, it’s good” experience combined with the current development trend of the front-end that makes Atomic CSS and its excellent product tailwind take off in the past period of time and become the shining star in the front-end field.

What: The idea of Tailwind

Tool class first

Tailwind offers greater freedom through the free combination of utility classes than traditional CSS frameworks, which typically extract common component styles and impose constraints while speeding up development.

At the same time, once the CSS rules are broken down to atomic granularity, as long as a set of utility classes are prepared in advance, there is no need to modify or add new CSS code or worry about CSS conflicts during the development process, whether SPA or micro front-end.

Responsive design

Tailwind supports responsive design with four screen width breakpoints by default:

/* Small (sm) */
@media (min-width: 640px) { /* ... */ }

/* Medium (md) */
@media (min-width: 768px) { /* ... */ }

/* Large (lg) */
@media (min-width: 1024px) { /* ... */ }

/* Extra Large (xl) */
@media (min-width: 1280px) { /* ... */ }
Copy the code

Tailwind advocates mobile first design philosophy:

<div class="text-center md:text-left"></div>
Copy the code

Component-friendly, customizable, and extensible

In addition to using the utility classes directly, Tailwind also supports the extraction of reusable components from the utility classes. Through its plug-in mechanism, components and custom tool classes can be extracted into JS plug-ins and shared among projects.

Tailwind’s theme is also modifiable and extensible.

How: Use tailwind

With all that said, I don’t know if you’re ready to try. The tutorials on tailwind’s website are very detailed, and there are few obstacles to learning about every aspect of Tailwind. Of course, if you want to get a feel for Tailwind, you can also check out the following minimalist guide.

Install and use

Using WebPack + PostCSS as an example, tailwind can also be used with other packaging tools and CSS preprocessors.

(Currently tailwind needs to work with PostCSS version 8. If you are creating projects using tools such as vUE – CLI or create-React-app, you may need to upgrade postCSS first.)

Installation:

yarn add tailwindcss
Copy the code

Next, create an index.css file:

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
Copy the code

Create tailwind.config.js by command or manually:

npx tailwindcss init
Copy the code

Configuration postcss – loader:

rules: [
  {
    test: /\.css$/i,
    use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
  },
  ...
]
Copy the code

To configure the postcss.config.js file:

module.exports = {
  plugins: [
    [
      "postcss-preset-env",
      {},
    ],
    require('tailwindcss'),
    require('autoprefixer'),
    isProductionMode && require('cssnano')(),
  ].filter(Boolean),
};
Copy the code

Tailwind generates a large number of utility classes, but we usually use a small portion of them later, so the production environment needs to work with PurgeCss to remove unused classes.

Edit the tailwind. Config. Js:

module.exports = {
  purge: {
    enabled: isProductionMode,
    content: ['./src/**/*.jsx'],
  },
};
Copy the code

preflight

Tailwind builds on normalize.css to create a basic style called Preflight (pre-flight, pre-check, derived from aircraft pre-takeoff inspection work), introduced via base:

@import "tailwindcss/base";Copy the code

Utility class

Tailwind’s utility classes cover most of the general requirements, and a detailed list is available on the official website:

  • layout
  • Elastic box
  • Grid layout
  • space
  • size
  • Typesetting (Typology)
  • background
  • A border
  • form
  • The special effects
  • The transition
  • deformation
  • interaction
  • svg
  • accessibility

It may take a while to get used to these classes, but once you get used to tailwind, you’ll enjoy it.

Return (<div className="bg-yellow-300 text-white text-center p-2 mt-4"> yellow background, white text </div>);Copy the code

Editor plug-in

Editor plugins are essential for ease of use, and if you’re using vscode, tailwind CSS intellisense is a good choice:

  • Automatic completion
  • lint
  • Hover preview: When the mouse hovers over the class name, the CSS corresponding to it is displayed

Such as:

.text-white {
  --tw-text-opacity: 1;
  color: rgba(255, 255, 255, var(--tw-text-opacity));
}

.mt-4 {
  margin-top: 1rem/* 16px */;
}
Copy the code

responsive

Tailwind preset four screen width breakpoints:

  • sm: min-width: 640px
  • md: min-width: 768px
  • lg: min-width: 1024px
  • xl: min-width: 1280px

When used, different reactive styles are set with [breakpoint]:[utility class]. It is recommended to follow the concept of mobile first, that is, set the basic style first, then use the style under the large screen to cover, for example:

<div class="w-16 md:w-32 lg:w-48">mobile first</div>
Copy the code

Variants

Pseudo-classes are also used by [pseudo-classes]:[utility classes], for example:

Class ="bg-teal-500 hover:bg-teal-600 focus: outlier-none "class="sm: bg-green-600"Copy the code

Pseudo classes include:

  • hover
  • focus
  • active
  • disabled
  • visited
  • child
  • last
  • odd
  • even
  • group & group-hover
  • group & group-focus
  • focus-within

Component extraction

Tailwind provides @apply for component extraction:

// jsx
return <div className="btn btn--blue">btn</div>

// index.css
.btn {
  @apply font-bold py-2 px-4 rounded;
}
.btn-blue {
  @apply bg-blue-500 text-white;
}
.btn-blue:hover {
  @apply bg-blue-700;
}
Copy the code

Generates prefixes for custom CSS

Tailwind provided @responsive and @ariphone to generate prefixes for our own CSS:

return ( <> <div className="xrotate-0 hover:xrotate-90"</div> <div className="xrotate-0 md:xrotate-90"</div> <div className="xrotate-0 md:hover:xrotate-90"</div> </> ); @responsive { @variants hover, focus { .xrotate-0 { transform: rotate(0deg); } .xrotate-90 { transform: rotate(90deg); } .xrotate-180 { transform: rotate(180deg); } .xrotate-270 { transform: rotate(270deg); }}}Copy the code

CSS File Structure

Tailwind recommends introducing Tailwind in a CSS file in a certain order, defining global styles, extracting components, and writing custom utility classes:

// Introduce the base library @tailwind base; H1 {@apply text-2xl; } a { @apply text-blue-600 underline; } // font @font-face {font-family: Proxima Nova; font-weight: 400; src: url(/fonts/proxima-nova/400-regular.woff) format("woff"); } // @tailwind components; BTN {@apply font-bold py-2 px-4 rounded; } .btn-blue { @apply bg-blue-500 text-white; } // @tailwind utilities; // aranjul variants, focus {/* aranjul variants, focus {/* aranjul variants */.xrotation-0 {transform: rotate(0deg); }}}Copy the code

Configuration files and topics

Configuration files allow us to edit and extend themes, modify generation rules for pseudo-classes, introduce plug-ins, and more:

module.exports = {
  theme: {},
  variants: {},
  plugins: [],
}
Copy the code

For the content of the topic, you can refer to the official documentation, here is not introduced

Plug-in mechanism

Tailwind’s plug-in mechanism provides a way to reuse extension components and utility classes:

// tailwind.config.js module.exports = { theme: { // ... Gradients: theme => ({'blue-green': [theme('colors.blue.500'), theme('colors.green.500')], 'purple-blue': [theme('colors.purple.500'), theme('colors.blue.500')], }), }, variants: { // ... }, plugins: [/ / registered plugins require ('/twplugins/utilities/gradients'), require ('/twplugins/comps/compA ')],}; // twplugins/utilities/gradients.js module.exports = plugin(({ addUtilities, e, theme, variants }) => { const gradients = theme('gradients', {}); const gradientVariants = variants('gradients', []); const utilities = _.map(gradients, ([start, end], name) => ({ [`.bg-gradient-${e(name)}`]: { backgroundImage: `linear-gradient(to right, ${start}, ${end})` } })); addUtilities(utilities, gradientVariants); }); // twplugins/comps/compA.js module.exports = plugin(({ addComponents, config }) => { const comps = { '.comp-a': { padding: '.5rem 1rem', borderRadius: '.25rem', fontWeight: '600', }, '.comp-a-primary': { backgroundColor: config('theme.colors.primary'), color: '#fff', }, '.comp-a-secondary': { backgroundColor: config('theme.colors.secondary'), color: '#fff', }, } addComponents(comps); });Copy the code

The last

Read the above introduction, did you move? Start developing your front-end projects with tailwindcss