Tailwind CSS
Tailwind CSS 是一个高度可定制的、实用工具优先的 CSS 框架,它使你能够通过组合小型、单一用途的类来构建现代网站界面,而无需写任何 CSS。
安装
1
| npm install -D tailwindcss postcss autoprefixer
|
此命令会在你的项目中安装三个依赖,它们分别是:
tailwindcss:Tailwind CSS 框架本身。
postcss:一个用于转换 CSS 的工具。
autoprefixer:一个 PostCSS 插件,用于自动添加浏览器供应商前缀到 CSS 规则中,确保跨浏览器的兼容性。
然后,再执行下面的命令,用于生成 tailwind.config.js
和 postcss.config.js
配置文件。
配置模板路径
在 tailwind.config.js
文件中添加所有模板文件的路径:
1 2 3 4 5 6 7 8 9 10 11
| export default { content: [ "./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}" ], theme: { extend: {}, }, plugins: [], }
|
将 Tailwind 指令添加到 CSS 文件中
修改 main.js 文件,引入 main.css :
1 2 3 4 5 6 7 8 9 10 11 12
| import '@/assets/main.css' # 引入
import { createApp } from 'vue' import App from '@/App.vue'
import router from '@/router'
const app = createApp(App)
app.use(router) app.mount('#app')
|
编辑 main.css
文件,清空里面初始化项目时自动生成的 css
代码,添加如下代码:
1 2 3
| @tailwind base; @tailwind components; @tailwind utilities;
|
重新构建
在项目中使用
编辑 /frontend/index.vue
文件,内容如下:
1 2 3 4 5
| <template> <div class="bg-green-300 inline">绿色</div> <div class="bg-yellow-300 ml-2 inline">黄色</div> <div class="bg-blue-300 ml-2 inline">蓝色</div> </template>
|
我们在 div
标签上添加了一些 Tailwind CSS 库中的样式类:
bg-green-300
: 绿色背景;
bg-yellow-300
: 黄色背景;
bg-blue-300
: 蓝色背景;
inline
: 相当于 display: inline;
ml-2
: 相当于 margin-left
;
响应式设计
通过在 Tailwind 类名前添加前缀,你可以轻松地应用不同的样式于不同屏幕尺寸:
1 2 3
| <div class="text-xs sm:text-lg md:text-xl lg:text-2xl"> 响应式字体 </div>
|
更多样式类,可查询官网:Installation - Tailwind CSS ,应有尽有!
Tailwind CSS 组件库:Flowbite
Flowbite 是一个基于 Tailwind CSS 创建的组件库,旨在帮助开发者快速构建现代、响应式的 Web 应用界面。
安装
在 tailwind.config.js
文件添加 Flowbit 插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| export default { content: [ "./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}" ], theme: { extend: {}, }, plugins: [ require('flowbite/plugin') ] }
|
另外, 还需要在 tailwind.config.js
文件中,添加 js
相关的文件,因为页面交互需要 js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export default { content: [ "./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}", "/node_modules/flowbite/**/*.js", ], theme: { extend: {}, }, plugins: [ require('flowbite/plugin') ] }
|
使用 Flowbite
Flowbit 支持的组件列表,大家可以去官网:Tailwind CSS Accordion - Flowbite 查看。
在 /frontend/index.vue
首页文件中添加 Navbar
导航栏头的源码,并将几处跳转的地方改为中文,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| <template> <nav class="bg-white border-gray-200 border-b dark:bg-gray-900"> <div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"> <a href="/" class="flex items-center"> <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 mr-3" alt="Flowbite Logo" /> <span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">嘿凡的前端项目</span> </a> <div class="flex md:order-2"> <button type="button" data-collapse-toggle="navbar-search" aria-controls="navbar-search" aria-expanded="false" class="md:hidden text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 mr-1"> <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> <span class="sr-only">Search</span> </button> <div class="relative hidden md:block"> <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> <span class="sr-only">Search icon</span> </div> <input type="text" id="search-navbar" class="block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="请输入关键词..."> </div> <button data-collapse-toggle="navbar-search" type="button" class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600" aria-controls="navbar-search" aria-expanded="false"> <span class="sr-only">Open main menu</span> <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" /> </svg> </button> </div> <div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-search"> <div class="relative mt-3 md:hidden"> <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> </div> <input type="text" id="search-navbar" class="block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Search..."> </div> <ul class="flex flex-col p-4 md:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"> <li> <a href="#" class="block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500" aria-current="page">首页</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 md:dark:hover:text-blue-500 dark:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">分类</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">标签</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">归档</a> </li> </ul> </div> </div> </nav> </template>
<script setup> import { onMounted } from 'vue' import { initCollapses } from 'flowbite'
onMounted(() => { initCollapses(); }) </script>
|
解释一下 <script>
中的代码:
onMounted
是一个生命周期钩子(lifecycle hook)。生命周期钩子是 Vue 组件在其生命周期的不同阶段可以调用的函数。onMounted
钩子在组件被挂载到 DOM 之后立即调用。这意味着,当此钩子被触发时,你可以安全地访问和操作组件的 DOM 元素;
initCollapses()
用于初始化 flowbite
的 collapse
组件,有了它,当页面在移动端展示时,点击菜单收缩按钮,可查看隐藏的菜单选项。
然后,在 main.css
中添加 <body>
标签的基本样式:
1 2 3 4 5 6 7
| body { font-family: -apple-system-font,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif; color: #4c4e4d; font-size: 16px; background: #f4f4f4; line-height: 1.6; }
|
添加【登录】超链接
1 2
| <div class="text-gray-900 ml-1 mr-1 hover:text-blue-700">登录</div>
|
注意,为了让登录超链接垂直居中,还需要在父级 <div>
中添加样式 items-center
, 以及边距调整。最终代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| <template> <nav class="bg-white border-gray-200 border-b dark:bg-gray-900"> <div class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"> <a href="/" class="flex items-center"> <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 mr-3" alt="Flowbite Logo" /> <span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">嘿凡的前端项目</span> </a> <div class="flex items-center md:order-2"> <button type="button" data-collapse-toggle="navbar-search" aria-controls="navbar-search" aria-expanded="false" class="md:hidden text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 mr-1"> <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> <span class="sr-only">Search</span> </button> <div class="relative hidden mr-2 md:block"> <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> <span class="sr-only">Search icon</span> </div> <input type="text" id="search-navbar" class="block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="请输入关键词..."> </div> <div class="text-gray-900 ml-1 mr-1 hover:text-blue-700">登录</div> <button data-collapse-toggle="navbar-search" type="button" class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600" aria-controls="navbar-search" aria-expanded="false"> <span class="sr-only">Open main menu</span> <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" /> </svg> </button> </div> <div class="items-center justify-between hidden w-full md:flex md:w-auto md:order-1" id="navbar-search"> <div class="relative mt-3 md:hidden"> <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" /> </svg> </div> <input type="text" id="search-navbar" class="block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Search..."> </div> <ul class="flex flex-col p-4 md:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700"> <li> <a href="#" class="block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500" aria-current="page">首页</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 md:dark:hover:text-blue-500 dark:text-white dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">分类</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">标签</a> </li> <li> <a href="#" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-100 md:hover:bg-transparent md:hover:text-blue-700 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700">归档</a> </li> </ul> </div> </div> </nav> </template>
<script setup> import { onMounted } from 'vue' import { initCollapses } from 'flowbite'
onMounted(() => { initCollapses(); }) </script>
|
总结
对后端来说,这样的组件非常友好,继续学习。