如何使用 Tailwind CSS 样式化表单

Avatar of Nick Basile
Nick Basile

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费积分!

如果您一直关注最新的 CSS 框架,您可能已经听说过最新的框架:Tailwind CSS。根据其文档,“Tailwind 是一个实用优先的 CSS 框架,用于快速构建自定义用户界面。”

实际上,这意味着使用各种与底层 CSS 属性密切相关的类。例如,将类似 .text-center 的类应用于元素意味着我们将它的 text-align 属性设置为 center。很简单,对吧?

使用这样的实用类,我们可以花更多时间迭代设计,避免过早抽象 CSS。然后,一旦我们对设计感到满意,Tailwind 可以轻松地将我们的实用程序提取到组件类中。

现在,我确信您知道,即使提到一个实用程序框架,也会邀请一定程度的喧嚣。在我们开始在 Twitter 或评论中对我大喊大叫,仅仅因为我提到了一个实用程序框架之前,让我们花点时间记住,Tailwind 只是我们可用的一个可能工具。

如果您不想将其添加到您的工具箱中,那么不用担心——您自己决定!但是,如果您有兴趣至少了解这个新工具,让我们一起看看如何构建一个注册表单。

话不多说,让我们使用 Tailwind 设置一个新的项目,编写一些 HTML 代码,并对其进行样式化。

设置

让我们首先创建一个目录,供我们从中工作。使用您的终端,导航到您要创建项目的目录,然后运行 mkdir <your-project-name>。现在,让我们 cd 到我们的新项目中,并按照 Tailwind 安装指南 进行操作。

由于我们想看到 Tailwind 的所有功能,让我们使用 npm 或 Yarn 使用以下命令安装它。

# Using npm
npm install tailwindcss --save-dev

# Using Yarn
yarn add tailwindcss --dev

安装完 Tailwind 后,我们现在可以通过运行 ./node_modules/.bin/tailwind init 生成配置文件。这会在我们项目的根目录中为我们生成一个 tailwind.js 文件。在这个文件中,我们可以调整 Tailwind 的默认设置,以满足我们项目的需要。对于这个项目,我们不应该做任何更改。

现在,让我们创建一个 CSS 文件,在其中我们可以管理自己的 CSS 并注入 Tailwind 样式。为此,我们可以从项目目录运行 touch styles.css

在这个新文件中,我们可以使用 Tailwind 的 @tailwind 指令将 preflightutilities 样式注入到我们的 CSS 中。preflight 包含所有基础样式和一些浏览器样式规范,而 utilities 添加了我们在配置文件中指定的实用程序类。因此,我们的 styles.css 文件应该如下所示

@tailwind preflight;

/* Here we can add any custom overrides */

@tailwind utilities;

/* Here we can add our own utilities or custom CSS */

如果您使用的是 PHPStorm,并且对 @tailwind 在 CSS 文件中的红色波浪线感到厌烦,只需在您使用它的位置上方添加 /*noinspection CssInvalidAtRule*/

设置好之后,我们可以运行 ./node_modules/.bin/tailwind build styles.css -o main.css 生成我们想在项目中使用的 CSS 文件。这似乎有点繁琐,但不要担心!Tailwind 与 Webpack、Gulp 或 Laravel Mix 等适当的构建工具一起使用,因此在大型项目中,您可以设置好并忘记它

这将完成我们的 Tailwind 设置!现在,我们可以开始编写 HTML 代码了。

我们的 HTML

在我们对注册表单进行样式化之前,我们需要构建它!首先,我们需要一个简单的 index.html 文件。因此,从根目录,您可以运行 touch index.html 来创建文件。然后,我们可以添加以下代码片段来开始。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tailwind Intro</title>
  <link rel="stylesheet" href="main.css">
</head>
<body>

</body>
</html>

如您所见,它是一个典型的 HTML 页面。这里唯一的区别是我们导入 main.css 文件,并为页面提供了一个描述性的标题。现在,让我们开始构建注册表单!

首先,让我们将两个嵌套的 <div> 元素添加到 <body> 标记的内部。

<body>
  <div>
    <div>
          
    </div>
  </div>
</body>

我们将使用外部 <div> 来定位页面,而内部 <div> 将是表单的包装器。现在,在内部 <div> 中,我们可以添加一个 <h1> 来标记表单,以及一个 <form>

<div>
  <h1>Sign Up</h1>
  <form action="/" method="post">
              
  </form>
</div>

我们现在真的在火力全开!要完成表单,我们只需要添加 <label> 元素、<input> 元素和 <button>。在添加它们时,让我们将每个 <label> <input> 对包装在一个 <div> 中,这样它们就会保持在一起。

<form action="/" method="post">
  <div>
    <label for="first_name">First Name</label>
    <input type="text" name="first_name" id="first_name">
  </div>
  <div>
    <label for="last_name">Last Name</label>
    <input type="text" name="last_name" id="last_name">
  </div>
  <div>
    <label for="email">Email</label>
    <input type="email" name="email" id="email">
  </div>
  <div>
    <label for="password">Password</label>
    <input type="password" name="password" id="password">
  </div>
  <button type="submit">Create Account</button>
</form>

最后,让我们添加一个链接,用于在表单下方访问登录页面。

<div>
  <!-- Form is here -->
  <a href="/login">Already have an account?</a>
</div>

将所有这些放在一起,我们的 HTML 代码将如下所示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tailwind Intro</title>
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <div>
    <div>
      <h1>Sign Up</h1>
      <form action="/" method="post">
        <div>
          <label for="first_name">First Name</label>
          <input type="text" name="first_name" id="first_name">
        </div>
        <div><label for="last_name">Last Name</label>
          <input type="text" name="last_name" id="last_name">
        </div>
        <div>
          <label for="email">Email</label>
          <input type="email" name="email" id="email">
        </div>
        <div>
          <label for="password">Password</label>
          <input type="password" name="password" id="password">
        </div>
        <button type="submit">Create Account</button>
      </form>
      <a href="/login">Already have an account?</a>
    </div>
  </div>
</body>
</html>

非常简单,对吧?现在,当我们在页面上看到它呈现出来时,我们应该看到类似这样的东西

如果看起来 <input> 消失了,不要惊慌;这只是浏览器重置在起作用。最后,我们准备看看这个 Tailwind CSS 是怎么做的了。

使用 Tailwind CSS

作为优秀的开发人员,让我们采用移动优先方法 来为我们的注册表单设置样式。因此,在 400px 的较小视窗宽度下,我们的页面看起来像这样

为我们的表单字段设置样式

让我们开始使用 Tailwind 为 <input> 设置样式。首先,让我们添加一个边框,这样我们就能在页面上看到它。为此,我们只需要添加 .border 类即可。因此,现在我们的第一个名字 <input> 将如下所示

<input class="border" type="text" name="first_name" id="first_name">

现在我们可以在屏幕上看到它了!

这有多容易?让我们继续添加一些填充,并将文本颜色稍微变淡。为此,我们只需要添加以下类:.py-2.px-3.text-grey-darkest

<input class="border py-2 px-3 text-grey-darkest" type="text" name="first_name" id="first_name">

使用前两个类,我们利用了 Tailwind 附带的填充比例,并将其垂直和水平应用于元素。如果您想定义自己的比例,只需跳到您的配置文件中,将其更改为您需要的比例即可。使用最后一个类,我们使用 Tailwind 的默认颜色调色板,并将元素的颜色更改为最深的灰色。

让我们更进一步。现在,我们可以将 <label> 定位到 <input> 的上方,并为它们添加一些样式。

<div class="flex flex-col mb-4">
  <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="first_name">First Name</label>
  <input class="border py-2 px-3 text-grey-darkest" type="text" name="first_name" id="first_name">
</div>

看看,我们的第一个名字字段看起来很棒!最好的部分是我真的不需要解释这些类在做什么——它们自己解释了!但为了确保我们都在同一页,让我快速浏览一下它们。

外部 <div>display 属性通过 .flex 设置为 flex,它的 flex-direction 通过 .flex-col 设置为 column。然后,由于 .mb-4,它在底部有一些边距。

同时,我们的 <label> 在底部有较少的边距,这要归功于 .mb-2。其余的类使我们的文本变为大写、加粗、变大(1.125rem)以及我们颜色调色板中最深的灰色。

总之,为我们的字段设置样式的一种非常快速简便的方法!现在,让我们将这些样式添加到其他字段,为按钮和链接设置样式,看看我们正在处理什么。

<form class="mb-6" action="/" method="post">
  <div class="flex flex-col mb-4">
    <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="first_name">First Name</label>
    <input class="border py-2 px-3 text-grey-darkest" type="text" name="first_name" id="first_name">
  </div>
  <div class="flex flex-col mb-4">
    <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="last_name">Last Name</label>
    <input class="border py-2 px-3 text-grey-darkest" type="text" name="last_name" id="last_name">
  </div>
  <div class="flex flex-col mb-4">
    <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="email">Email</label>
    <input class="border py-2 px-3 text-grey-darkest" type="email" name="email" id="email">
  </div>
  <div class="flex flex-col mb-6">
    <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="password">Password</label>
    <input class="border py-2 px-3 text-grey-darkest" type="password" name="password" id="password">
  </div>
  <button class="block bg-teal hover:bg-teal-dark text-white uppercase text-lg mx-auto p-4 rounded" type="submit">Create Account</button>
</form>
<a class="block w-full text-center no-underline text-sm text-grey-dark hover:text-grey-darker" href="/login">Already have an account?</a>

添加悬停样式

现在事情开始看起来好多了!在这段代码中,所有内容都应该非常清楚。但是,我们添加了一件新东西:一个状态变体。如果我们看看 <button>,我们可以看到它的实际应用。

<button class="block bg-teal hover:bg-teal-dark text-white uppercase text-lg mx-auto p-4 rounded" type="submit">Create Account</button>

如果您看看 .bg-teal 之后的类,您会看到我们添加了 hover: 前缀到 .bg-teal-dark。这些前缀允许我们在悬停和聚焦时设置元素的样式,也允许我们使用断点!总而言之,这是一个非常强大的 Tailwind 功能,它允许我们非常快地创建动态的响应式 UI

现在,让我们通过将表单定位在屏幕中央并添加一个彩色的页面背景,来完成我们的移动视图。

<div class="flex items-center h-screen w-full bg-teal-lighter">
  <div class="w-full bg-white rounded shadow-lg p-8 m-4">
    <h1 class="block w-full text-center text-grey-darkest mb-6">Sign Up</h1>
    <form class="mb-4" action="/" method="post">
      <div class="flex flex-col mb-4">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="first_name">First Name</label>
        <input class="border py-2 px-3 text-grey-darkest" type="text" name="first_name" id="first_name">
      </div>
      <div class="flex flex-col mb-4">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="last_name">Last Name</label>
        <input class="border py-2 px-3 text-grey-darkest" type="text" name="last_name" id="last_name">
      </div>
      <div class="flex flex-col mb-4">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="email">Email</label>
        <input class="border py-2 px-3 text-grey-darkest" type="email" name="email" id="email">
      </div>
      <div class="flex flex-col mb-6">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="password">Password</label>
        <input class="border py-2 px-3 text-grey-darkest" type="password" name="password" id="password">
      </div>
      <button class="block bg-teal hover:bg-teal-dark text-white uppercase text-lg mx-auto p-4 rounded" type="submit">Create Account</button>
    </form>
    <a class="block w-full text-center no-underline text-sm text-grey-dark hover:text-grey-darker" href="/login">Already have an account?</a>
  </div>
</div>

砰砰,我们已经拥有了一个美观的移动注册表单!但是,当我们在更大的屏幕上查看它时会发生什么?

响应式设计

它当然比我们普通的 HTML 好,但还需要一些改进。让我们使用一些响应式状态变体,并为更大的屏幕样式化它。

<div class="flex items-center h-screen w-full bg-teal-lighter">
  <div class="w-full bg-white rounded shadow-lg p-8 m-4 md:max-w-sm md:mx-auto">
    <h1 class="block w-full text-center text-grey-darkest mb-6">Sign Up</h1>
    <form class="mb-4 md:flex md:flex-wrap md:justify-between" action="/" method="post">
      <div class="flex flex-col mb-4 md:w-1/2">
        <label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest" for="first_name">First Name</label>
        <input class="border py-2 px-3 text-grey-darkest md:mr-2" type="text" name="first_name" id="first_name">
      </div>
      <div class="flex flex-col mb-4 md:w-1/2">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest md:ml-2" for="last_name">Last Name</label>
        <input class="border py-2 px-3 text-grey-darkest md:ml-2" type="text" name="last_name" id="last_name">
      </div>
      <div class="flex flex-col mb-4 md:w-full">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="email">Email</label>
        <input class="border py-2 px-3 text-grey-darkest" type="email" name="email" id="email">
      </div>
      <div class="flex flex-col mb-6 md:w-full">
        <label class="mb-2 uppercase font-bold text-lg text-grey-darkest" for="password">Password</label>
        <input class="border py-2 px-3 text-grey-darkest" type="password" name="password" id="password">
      </div>
      <button class="block bg-teal hover:bg-teal-dark text-white uppercase text-lg mx-auto p-4 rounded" type="submit">Create Account</button>
    </form>
    <a class="block w-full text-center no-underline text-sm text-grey-dark hover:text-grey-darker" href="/login">Already have an account?</a>
  </div>
</div>

多亏了我们的响应式前缀,我们的注册表单看起来好多了!让我们看看我们的<form>,找一些例子。

<form class="mb-4 md:flex md:flex-wrap md:justify-between" action="/" method="post">
  <!-- ... -->
</form>

就像我们的hover:前缀一样,我们只在满足条件时才应用带前缀的类。在这种情况下,这意味着我们只在页面min-width768px时才将 flex 样式应用于我们的<form>

将实用程序提取到组件

现在我们已经完成了表单的原型设计,我们可以将实用程序类提取到组件类中。让我们从提取我们的<input>类开始。

<input class="border py-2 px-3 text-grey-darkest" type="password" name="password" id="password">

正如我们所看到的,我们的<input>上有一些类。我们可以使用 Tailwind 的@apply指令将这些类提取到我们的 CSS 中。@apply允许我们将实用程序类使用的相同样式应用于新的类。因此,在我们的styles.css文件的底部,我们可以添加以下内容

.field {
  @apply .border .py-2 .px-3 .text-grey-darkest;
}

然后,在我们重新编译 Tailwind 文件后,我们的<input>只需要.field类。

<input class="field" type="password" name="password" id="password">

正如您所看到的,使用 Tailwind,我们获得了实用程序类和组件类的最佳效果!我们可以使用实用程序类快速迭代,并在开始看到模式时仍然提取组件类。

更好的是,我们可以将它们混合起来,处理那些没有意义的专用组件类的情况。

最终 CSS

将这种思想应用于我们代码的其余部分,我们的 CSS 和 HTML 将如下所示。

@tailwind preflight;

/* Here we can add any custom overrides */

.field {
  @apply .border .py-2 .px-3 .text-grey-darkest;
}

.field-label {
  @apply .uppercase .font-bold .text-lg .text-grey-darkest .mb-2;
}

.field-group {
  @apply .flex .flex-col;
}

.btn {
  @apply .block .text-white .uppercase .text-lg .p-4 .rounded;
}

.btn-teal {
  @apply .bg-teal;
}

.btn-teal:hover {
  @apply .bg-teal-dark;
}

.link {
  @apply .block .no-underline .text-sm;
}

.link-grey {
  @apply .text-grey-dark;
}

.link-grey:hover {
  @apply .text-grey-darker;
}

@tailwind utilities;

/* Here we can add our own utilities or custom CSS */

最终 HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tailwind Intro</title>
  <link rel="stylesheet" href="main.css">
</head>
<body>
    <div class="flex items-center h-screen w-full bg-teal-lighter">
      <div class="w-full bg-white rounded shadow-lg p-8 m-4 md:max-w-sm md:mx-auto">
        <h1 class="block w-full text-center text-grey-darkest mb-6">Sign Up</h1>
        <form class="mb-4 md:flex md:flex-wrap md:justify-between" action="/" method="post">
          <div class="field-group mb-4 md:w-1/2">
            <label class="field-label" for="first_name">First Name</label>
            <input class="field md:mr-2" type="text" name="first_name" id="first_name">
          </div>
          <div class="field-group mb-4 md:w-1/2">
            <label class="field-label md:ml-2" for="last_name">Last Name</label>
            <input class="field md:ml-2" type="text" name="last_name" id="last_name">
          </div>
          <div class="field-group mb-4 md:w-full">
            <label class="field-label" for="email">Email</label>
            <input class="field" type="email" name="email" id="email">
          </div>
          <div class="field-group mb-6 md:w-full">
            <label class="field-label" for="password">Password</label>
            <input class="field" type="password" name="password" id="password">
          </div>
          <button class="btn btn-teal mx-auto" type="submit">Create Account</button>
        </form>
        <a class="link link-grey w-full text-center" href="/login">Already have an account?</a>
    </div>
  </div>
</body>
</html>

我们已经提取了重复的类,并保留了其余的。当我们发现自己构建类似的组件时,我们可以提取更多类!

总结

哇!我们在本文中确实涵盖了很多内容。我们从通过构建快速表单来锻炼我们的 HTML 肌肉开始,然后我们使用 Tailwind 对我们的样式采用移动优先的方法。在此过程中,我们看到了如何使用 Tailwind 的实用程序类快速设置元素的样式。然后,我们使用状态变体添加了一些动态样式。最后,我们看到了如何在提取重复类到组件类时既能保持蛋糕又能吃蛋糕。

我希望您能够体验到 Tailwind 如何在您自己的项目中产生影响。如果您想尝试一下这个项目,请随时克隆仓库并自己尝试使用 Tailwind。像往常一样,随时在Twitter上向我提出任何问题。直到下次,祝您编码愉快!