如何基于 tailwindcss 轻松实现多端自适应布局方案 🫠🫠🫠

3,789 阅读6分钟

最近一直在使用 tailwindcss 编写一些项目,我们希望一套代码能让产品在不同的设备上都能有良好的用户体验,同时,为了节省人力成本,希望在同一套代码上去针对不同的屏幕尺寸去做样式适配。

如果你有这样的需求,那么 tailwindcss 作为 css 框架那么它是非常合适的

tailwind 断点

TailwindCSS 的断点系统是基于移动优先设计理念的,这意味着默认情况下样式首先应用于所有屏幕尺寸,然后通过断点应用于更大的屏幕。TailwindCSS 提供了多种断点类来处理不同屏幕尺寸下的样式变化。

在默认情况下,所有未指定断点的类都会应用于所有设备尺寸,例如:

<div class="text-center">Hello World</div>

20240814220656

这段代码中的 text-center 类将应用于所有屏幕尺寸。

在 tailwind 中,默认有这些断点命名及其对应的屏幕尺寸:

  1. sm (small) 适用于 ≥640px 的屏幕宽度

  2. md (medium) 适用于 ≥768px 的屏幕宽度

  3. lg (large) 适用于 ≥1024px 的屏幕宽度

  4. xl (extra large) 适用于 ≥1280px 的屏幕宽度

  5. 2xl (2x extra large) 适用于 ≥1536px 的屏幕宽度

断点通过在类名前加上断点前缀来实现。例如:

<div
  class="text-sm sm:text-base md:text-lg lg:text-xl xl:text-2xl lg:text-red-600"
>
  Responsive Text
</div>

20240814221126

20240814221400

两者代码一样,但是当屏幕大小不同的时候,字体颜色就变得不同了,字体大小也变得不同了。

  1. text-sm: 所有屏幕尺寸默认使用 text-sm 类。

  2. sm:text-base: 当屏幕宽度 ≥640px 时,文本大小为 text-base。

  3. md:text-lg: 当屏幕宽度 ≥768px 时,文本大小为 text-lg。

  4. lg:text-xl: 当屏幕宽度 ≥1024px 时,文本大小为 text-xl。

  5. xl:text-2xl: 当屏幕宽度 ≥1280px 时,文本大小为 text-2xl。

  6. lg:text-red-600:当屏幕宽度 ≥1024px 时,文本颜色为红色。

TailwindCSS 允许我们在配置文件 tailwind.config.js 中自定义断点。以下是一个示例

/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    extend: {
      screens: {
        moment: "1024px",
      },
    },
  },
  plugins: [],
};

这个配置添加了一个名为 moment 的自定义断点,适用于屏幕宽度 ≥1024px。

20240814222103

你看看,我们的配置生效了。

关于断点的使用方式,我们应该基于移动优先的策略,从移动设备开始设计,然后逐步增强到更大的屏幕尺寸。

使用 flex 布局实现响应式

在布局框架定下来后,就是局部的布局变化了,常见的就是在某个断点后,需要把原来的水平布局变成垂直布局,或者反过来。我们还可以基于断点,在某个阶段下隐藏。

如下代码所示:

<article class="border rounded-2xl shadow-lg bg-white overflow-hidden w-full">
  <header class="flex flex-col sm:flex-row">
    <div class="flex-1 p-4">
      <div class="flex items-center mb-2">
        <img
          src="https://cdn.pixabay.com/photo/2024/07/15/16/09/bird-8897237_1280.jpg"
          alt="Jesse Williams's avatar"
          class="w-12 h-12 rounded-full mr-4 shadow-md"
        />
        <div>
          <p class="text-sm text-gray-600">
            <strong>Jesse Williams</strong> for KitOps
          </p>
          <time class="text-xs text-gray-400">Aug 9 (23 hours ago)</time>
        </div>
      </div>
      <h2 class="text-lg font-bold">
        What's your biggest AI development challenge?
      </h2>
      <p class="text-gray-600 mt-2 line-clamp-2">
        Write better tests! I personally sometimes fall into the mistake of
        testing the happy paths only...
      </p>
      <ul class="flex flex-wrap gap-2 mt-2">
        <li>
          <span class="bg-gray-200 text-xs px-2 py-1 rounded-full shadow-sm">
            #discuss
          </span>
        </li>
        <li>
          <span class="bg-gray-200 text-xs px-2 py-1 rounded-full shadow-sm">
            #datascience
          </span>
        </li>
        <li>
          <span class="bg-gray-200 text-xs px-2 py-1 rounded-full shadow-sm">
            #machinelearning
          </span>
        </li>
        <li>
          <span class="bg-gray-200 text-xs px-2 py-1 rounded-full shadow-sm">
            #devdiscuss
          </span>
        </li>
      </ul>
    </div>
    <figure class="w-full sm:w-48 flex-shrink-0">
      <img
        src="https://cdn.pixabay.com/photo/2024/07/15/16/09/bird-8897237_1280.jpg"
        alt="Article Cover"
        class="w-full h-full object-cover rounded-r-2xl sm:rounded-tr-2xl sm:rounded-br-2xl"
      />
    </figure>
  </header>
  <footer
    class="px-4 py-2 flex items-center justify-between text-gray-500 text-sm"
  >
    <div class="flex items-center">
      <span class="mr-4">❤️‍🔥 33 Reactions</span>
      <span>💬 3 Comments</span>
    </div>
    <div class="text-xs text-gray-400 flex items-center">
      <span class="mr-2">1 min read</span>
      <button
        class="text-gray-500 hover:text-blue-500 transition-colors"
        aria-label="Comment"
      >
        💬
      </button>
    </div>
  </footer>
  <section class="p-4 bg-gray-100 flex items-start rounded-b-2xl">
    <img
      src="https://cdn.pixabay.com/photo/2024/07/15/16/09/bird-8897237_1280.jpg"
      alt="Javis V. Pérez's avatar"
      class="w-8 h-8 rounded-full mr-4 shadow-md"
    />
    <div class="flex-1">
      <p class="text-sm">
        <strong>Javis V. Pérez</strong>
        <time class="text-xs text-gray-400">23 hours ago</time>
      </p>
      <p class="text-gray-700 mt-1">
        Write better tests! I personally sometimes fall into the mistake of
        testing the happy paths only...
      </p>
      <button class="text-blue-500 mt-2 hover:underline">See more</button>
    </div>
  </section>
</article>

我们先来看看效果,可以看到,是已经实现了响应式的效果了的,简简单单的一些代码就轻松实现了响应式,而不需要像我们之前那样来编写媒体查询来实现。

2024-08-14 23.05.07.gif

接下来我们来对代码进行简单的解释,首先是整体布局:

<article
  class="border rounded-2xl shadow-lg bg-white overflow-hidden w-full"
></article>

<article> 标签的 w-full 类使其宽度在所有屏幕尺寸上都占满父元素的全部宽度,这样可以确保内容自适应容器的大小。

<header class="flex flex-col sm:flex-row"></header>

<header> 标签使用了 flex 类,使其内部的子元素按 Flexbox 布局排列。默认情况下,flex-col 类使子元素按列方向垂直排列。

  1. flex-col: 在小屏幕上(sm 以下的尺寸),子元素按列方向排列,确保内容在垂直方向上展示,方便在移动设备上阅读。

  2. sm:flex-row: 在屏幕尺寸达到 sm(≥640px)时,flex-row 类会将子元素按行方向水平排列,适合较大的屏幕。这意味着图片和文字内容会并排显示。

在图片和文本区域的布局上,它的代码如下:

<div class="flex-1 p-4">...</div>
<figure class="w-full sm:w-48 flex-shrink-0">...</figure>
  1. flex-1: 该类应用在包裹文本内容的 <div> 上,使其占据剩余的空间,从而在大屏幕上与图片区域合理分配空间。

  2. p-4: 添加了 p-4 类,用来设置 16px 的内边距,确保内容不会紧贴边界。

  3. w-full: 在小屏幕上,图片的宽度占据整行(w-full),这样图片和文字都在各自的独立行中显示。

  4. sm:w-48: 在屏幕尺寸达到 sm 时,图片宽度被限制为 192px(w-48),从而与文本区域并排显示,适应更大的屏幕。

该组件大嘎就是通过以上布局和 TailwindCSS 类的组合,这段代码实现了一个高度响应式的界面,能够根据不同的屏幕尺寸自适应调整布局,确保良好的用户体验。

大多数情况下,一个用户只会看到某个断点下的页面,所以,我们可以根据当前的断点,来决定加载哪些组件,这样可以减少不必要的代码加载,减少 js 体积,提高页面加载速度。

总结

基于 tailwindcss 的多端自适应布局方案,可以让我们在同一套代码上去针对不同的屏幕尺寸去做样式适配,可以大大减少我们的开发成本。

TailwindCSS 提供了丰富的实用类,可以直接在 HTML 中快速编写响应式样式,无需编写大量的自定义 CSS 代码。我们可以通过简单的类名组合实现复杂的响应式设计。

由于所有样式都是通过类名直接应用在 HTML 元素上,样式和布局逻辑都集中在一起,使得代码更易于理解和维护,减少了样式冲突的可能性。并且 TailwindCSS 通过预定义的设计系统,如颜色、间距、字体大小等,确保了不同组件之间的样式一致性,让设计更具整体性。

最后分享两个我的两个开源项目,它们分别是:

这两个项目都会一直维护的,如果你想参与或者交流学习,可以加我微信 yunmz777 如果你也喜欢,欢迎 star 🚗🚗🚗