Tailwind是一种刚开始用会觉得麻烦,熟练了以后会觉得好香的东西(。
利用Tailwind封装的很方便的媒体查询(media query)功能,灵活实现在flex布局下网页对其他页面尺寸的适配。Tailwind官方提供了一个在线玩耍的平台:Tailwind Play
本篇可参考前篇一起食用。
先构建一个桌面端网站
<div class="flex h-screen w-screen flex-row">
<!-- sidebar -->
<aside class="h-full w-56 flex-col bg-slate-100 p-6 transition-transform">
<img src="/img/logo.svg" class="h-5" alt="Tailwind Play" />
<div class="p-8">
<ul class="flex flex-col gap-4">
<li>SideMenu1</li>
<li>SideMenu2</li>
<li>SideMenu3</li>
<li>SideMenu4</li>
</ul>
</div>
</aside>
<!-- header + body + footer -->
<div class="z-40 flex w-10 flex-auto flex-col">
<header class="w-full p-6 flex h-14 flex-shrink-0 items-center justify-between bg-slate-300 transition-transform">
<!-- menus -->
<div class="flex gap-3">
<div>menuA</div>
<div>menuB</div>
<div>menuC</div>
<div>menuD</div>
</div>
<!-- user -->
<div class="cursor-pointer">user</div>
</header>
<!-- body -->
<div class="w-full flex-auto overflow-auto bg-slate-400 p-4">
<div class="flex h-[1000px] w-[800px] min-w-full flex-col bg-white pt-4"></div>
</div>
<!-- footer -->
<div class="h-12 flex-shrink-0 bg-slate-50 p-4">footer</div>
</div>
</div>
布局设计如下:
- 主体是flex行布局,由左侧的Sidebar和右侧的部分组成,方便在后续响应式调整的时候单独对Sidebar进行处理。
- 右侧为flex列布局,从上到下是Header、Body(主体内容)、Footer部分。
布局细节:
- Siderbar一般是定宽的,所以设置了
w-56
,而右侧存放主体部分,内容可能溢出,不能在布局的时候就确定大小,因此在flex布局里可以设置为flex: 1 1 auto
,让它填充父组件剩余的部分,用tailwind写就是flex-auto
。注意:还需要给右侧布局增加一个不大的固定宽度(w-10
),虽然这个宽度不会实际体现出来,但会对子元素的溢出行为产生约束,否则右侧部分会把父组件也撑大,本来只是想这个部分溢出滚动,最后会变成整个页面溢出滚动。 - 因为body内容的尺寸无法确定,为了不因为body的尺寸变化导致flex布局中的其他元素收到挤压(Sidebar、Header、Footer),需要给这些元素添加
flex-shrink: 0
,保证它们的尺寸不会受影响,用tailwind写就是flex-shrink-0
目前这个框架是没有响应式设计的,尺寸的改变并不会引起布局的变化:
媒体查询断点
浏览器自带的调试工具有几个预设的宽度断点:
- 4K - 2560px
- 大型笔记本电脑 - 1440px
- 笔记本电脑 - 1024px
- 平板电脑 - 768px
- 大型移动设备 - 425px
- 中型移动设备 - 375px
- 小型移动设备 - 320px
tailwind可以在config文件里对这些屏幕断点值进行自定义,在这个项目中,我们自定义小设备是在768px以下的,可以这么写:
export default {
theme: {
extend: {
// ...
},
screens: {
sm: '768px', // 自定义
},
},
plugins: [],
}
确定响应后的设计
我们希望网站可以适配更小尺寸的设备,在网页变窄时可以把Sidebar收起来,其他地方不变,再在Header上增加一个开关,用于切换Siderbar的出现和隐藏。
注意:tailwind的逻辑是mobile first,因此默认情况下设置的class会对小屏幕生效,加上媒体查询断点(比如sm、md、lg等)之后,tailwind才会在相应的尺寸使用断点后的设置。
首先我们处理Sidebar:
- 由于这是个flex布局,为了让右边能够占满整个屏幕,我们可以将左边Sidebar的
flex-basis
置为0,tailwind写法是basis-0
。 - 为了让flex可以自由显示/隐藏同时不影响屏幕内容,我们可以把它的位置(position)改为
absolute
,让它相对于整个屏幕进行定位,也就浮动在了flex布局上方。
<!-- sidebar -->
<!-- 尽量成对书写class,有sm:前缀的是在大屏幕出现的,默认是小屏幕 -->
<aside class="
hidden sm:visible
absolute sm:relative sm:flex
z-50 sm:z-10
basis-0 sm:basis-56
h-full w-56 flex-shrink-0 p-6
bg-slate-100
flex-col">
<img src="/img/logo.svg" class="h-5" alt="Tailwind Play" />
<div class="p-8">
<ul class="flex flex-col gap-4">
<li>SideMenu1</li>
<li>SideMenu2</li>
<li>SideMenu3</li>
<li>SideMenu4</li>
</ul>
</div>
</aside>
把logo的位置换一下(Sidebar上面的隐藏,Header上面的露出来,再增加一个最左侧的Sidebar开关)
<header class="flex h-14 flex-shrink-0 items-center justify-between bg-slate-300 transition-transform">
<!-- logo & menu -->
<div class="flex gap-3 p-3">
<!-- logo -->
<div class="visible flex gap-3 sm:hidden">
<button data-drawer-target="default-sidebar" data-drawer-toggle="default-sidebar" aria-controls="default-sidebar" type="button" class="items-center rounded-lg text-sm text-gray-500">
<span class="sr-only">Open sidebar</span>
<svg class="h-5 w-5" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path clip-rule="evenodd" fill-rule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"></path>
</svg>
</button>
<img src="/img/logo.svg" class="h-5" alt="Tailwind Play" />
</div>
<!-- menus -->
<div class="gap-3 flex flex-row">
<div>menuA</div>
<div>menuB</div>
<div>menuC</div>
<div>menuD</div>
</div>
</div>
<!-- user -->
<div class="flex gap-3 p-4">
<div class="cursor-pointer">user</div>
</div>
</header>
当屏幕尺寸较小时,Sidebar就可以收起来了:
同理也可以把header上面的Menu收起来:
<!-- menus -->
<!-- 用select下拉节省空间 -->
<select class="visible sm:hidden">
<option select>menuA</option>
<option select>menuB</option>
<option select>menuC</option>
<option select>menuD</option>
</select>
<!-- 原来的menus -->
<div class="gap-3 hidden sm:flex sm:flex-row">
<div>menuA</div>
<div>menuB</div>
<div>menuC</div>
<div>menuD</div>
</div>
body部分的布局细节
为了整体布局的一致性,我们希望body的宽度要最大化地容纳内容(width: max-content
),但在屏幕特别大的时候,希望body宽度可以铺满整个父组件(width: 100%
),这样比较好看,但往往这两者不能同时设置:
- 设置
w-max
时,会出现屏幕很大时body铺不满的情况:
- 设置
w-full
或max-w-ful
l时,内容不会有溢出滚动,在某些布局下是不利的:
解决方法是同时设置w-max
和min-w-full
:
<div class="w-full flex-auto overflow-auto bg-slate-400 p-4">
<div class="flex h-[1000px] w-max min-w-full flex-col bg-white pt-4">
<span>内容很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长</span>
</div>
</div>