Flexbox 太棒了!
介绍
介绍
昨天我用 Flexbox 重构了一个Codesandbox,它显示“有权势的人”的卡片,包括他们的姓名、角色、爱好和一张图片。
我想完成两件事。
- 使用 flexbox 构造卡片本身。
- 在较宽的屏幕上以响应式一行卡片的形式显示所有卡片,或在较窄的屏幕上以单列卡片的形式显示所有卡片。
这篇文章不仅会尝试分解我如何使用 CSS 和 HTML 来实现这一点,还会分解事先设计卡片的过程。
第一步 - 设计
我使用Excalidraw来模拟网站上的元素。Excalidraw 能让你快速在屏幕上看到你的想法,并在你开始编码时提供便捷的参考。
我设计出了这张卡片的模型。
看起来不错。现在最难的部分是让我的卡片看起来和用起来符合我的要求。
弹性框资源
如果你从未尝试过使用 CSS 的 flex 属性,我强烈建议你尝试一下Flexbox Froggy,它能让学习 flexbox 变成一场游戏。我保证,只要你多看几遍这个教程,你就能更好地理解如何使用 flexbox。
另一个很好的资源是 CSS-Tricks 的Flexbox 完整指南。
第二步 - 了解你的设计
当我开始将屏幕上的每个元素想象成一个独立的迷你屏幕时,我开始理解弹性盒。例如,卡片就是它自己包含的环境。卡片内部的内容不必关心其外部的元素。所有卡片所在的布局也是它自己的环境。它不必关心屏幕上的其他元素。
我认为从最外层的“环境”(在 HTML 中用 表示)开始,<div>
然后向内推进会很有帮助。我的 Powerful Person 网站的最外层环境就是用<div>
我的 HTML 中的最外层 表示的。
<div className="App">
CSS
.App {
text-align: center;
}
该酒店text-align: center;
将“有权势的人”标题置于中心。
接下来,我想让所有卡片按行显示。我需要创建另一个“环境”,在其中为卡片应用 flex 属性,并让它们按行显示。
看一下这张图片,看看我是如何分解 CSS 和 HTML 的:
我创建了一个新的 CSS 类.wrapper
,它将“包裹”我的所有卡片并规定它们的布局。
.wrapper{
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
编辑:有人指出这row
是该属性的默认值flex-direction
。这使得包含它.wrapper
变得多余。我将把它保留在这里,以便其他人可以借鉴,并且我以后需要时也可以参考它。
Flexbox 有很多很棒的属性,其中之一就是flex-direction
。你可以设置行、列、反转行和反转列。flex-direction: row
将卡片放置在单个水平行中。
什么是flex-wrap: wrap
?
为了说明这一点,我将注释掉该行。
.wrapper{
flex-direction: row;
/* flex-wrap: wrap; */
justify-content: center;
}
哎呀。卡片都溢出屏幕了。
嗯,这不太好。wrap 属性会将最后一个屏幕外的元素向下移动,在父 div 的范围内创建一个新行。
justify-content: center;
很容易理解。我们来看一下注释掉这行代码的例子,然后再重新添加它。
.wrapper{
flex-direction: row;
flex-wrap: wrap;
/* justify-content: center; */
}
回来justify-content: center;
了。
换挡 - 响应式 CSS
就在那时,我意识到我正在创建“桌面优先”的设计,并且我想转向“移动优先”的设计实践。
响应式网页设计使网站能够根据屏幕尺寸调整其在屏幕上的显示方式。这是通过 CSS“媒体查询”实现的,开发者可以根据他们希望网站的行为方式来定义这些媒体查询。如果您不熟悉 CSS 媒体查询,请查看w3schools.com上的这些示例。
CSS 媒体查询超出了这篇文章的范围(一旦我写了一个,我会在这里链接它)。
但是,我必须谈谈如何重构我的.wrapper
类以在移动设备上的单列中显示我的卡片,并responsive.css
为我的包装类添加第二个带有媒体查询的 CSS 文件,以便在屏幕足够宽时将弹性方向更改回行。
首先是我的重构,移动优先的 CSS.wrapper
类。
.wrapper {
display: flex;
flex-direction: column;
}
现在我的所有卡片都垂直排列成一列。无论屏幕尺寸如何,我的卡片现在始终垂直排列成一列。
我希望它们在大屏幕上仍然能按行显示。我需要一个 CSS 媒体查询。
(不要忘记导入responsive.css
到你的顶级组件中。对我来说就是这样App.js
。)
/* responsive.css */
@media only screen and (min-width: 1100px) {
.wrapper{
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
}
编辑:我上面提到 havingflex-direction: row;
是多余的,但在这里它不是多余的。这个媒体查询覆盖了flex-direction: column;
我之前重构的 。
我告诉我的.wrapper
班级,每当屏幕设备为 1100px 或更大时,将其弹性方向改回行。
忏悔
事实上,我是先创建卡片的。之后我才弄清楚如何以行或列的方式显示所有卡片。之后我才从桌面优先设计转向移动优先设计。
这是有原因的。起初我使用的是“虚拟数据”,屏幕上只有一张卡片。我还没有创建本地 API。所以不需要定义布局。
但是。首先,有必要从最外层环境到最内层环境(我的卡片)来讨论 flex 的概念。如果你正在创建自己的布局,并且想看看元素在屏幕上的显示效果,你可以轻松地用 CSS 占位符替换卡片。
你可以这样做:
.card {
align-self: center;
background-color: rgb(20, 20, 20);
margin: 1rem;
width: 90%;
height: 15rem;
}
然后是你的 HTML:
<div className="wrapper">
<div className="card" />
<div className="card" />
<div className="card" />
<div className="card" />
<div className="card" />
<div className="card" />
<div className="card" />
<div className="card" />
</div>
这将模拟映射并渲染到您的屏幕上的多张卡。
步骤 3(有点)- 创建卡片
看看我制作的这个 Excalidraw 草图:
记住我的思维模型:页面上的每个元素都可以被视为其自身的“环境”。每张卡片都存在于.wrapper
环境中,但卡片内部的元素并不知道如何表现,除非我们创建一个新的环境来规定其外观和行为。
每个.card
div 都有自己的“包装器”div,称为.row
。
.row {
display: flex;
flex-direction: row;
}
这里我们让卡片内的内容以水平行的形式显示,从左到右彼此相邻。
接下来,类中的每个元素.row
将被“包装”在名为的 div 中.column
。
.column {
display: flex;
flex-direction: column;
flex: 1;
}
.column
现在,由于,类内的任何元素都将垂直显示flex-direction: column;
。
什么是flex: 1
?
flex:
positive-number
等同于 flex: 1 0px。它使弹性项目具有弹性,并将弹性基础设置为零,从而使项目获得指定比例的剩余空间。如果弹性容器中的所有项目都使用此模式,则它们的大小将与指定的弹性因子成比例。
现在,.column
类中的所有内容都会响应display: flex;
flex 属性,我们可以使用它。看一下我的其余 CSS,它们规定了卡片内容的布局:
.info {
margin-top: .5rem;
margin-left: 1rem;
}
h1 {
align-self: center;
font-family: 'Bangers', cursive;
font-weight: lighter;
font-size: 3rem;
color: rgb(20, 20, 20);
}
h4 {
text-align: left;
color: rgba(255, 255, 255, 0.8);
margin-top: -.5rem;
}
p {
text-align: left;
color: rgba(255, 255, 255, 0.5);
margin-top: -.5rem;
}
ul {
margin-top: -.5rem;
}
li {
text-align: left;
color: rgba(255, 255, 255, 0.8);
font-weight: bold;
}
img {
align-self: flex-start;
border-radius: 2rem;
object-fit: cover;
height: 8rem;
width: 8rem;
}
你会注意到每个 HTML 元素(h1、h4、li、p 和 img)都使用了 flex 属性,text-align
也就是align-self
。因为它们位于.column
类内部,所以它们会响应display: flex
属性。
最后是我的完整App.js
组件。
import React from "react";
import "./styles.css";
import "./responsive.css"
import PersonData from './data/personData'
export default function App() {
return (
<div className="App">
<h1>Powerful People</h1>
<div className="wrapper">
{PersonData.map(person => {
return (
<div className="card" key={person.id}>
<div className="row">
<div className="column">
<img src={person.url} alt={person.name} />
</div>
<div className="column">
<div className="info">
<p>Full name</p>
<h4>{person.name}</h4>
<p>Profession</p>
<h4>{person.role}</h4>
<p>Hobbies</p>
<ul>
{person.hobbies.map((hobby, i) => {
return(
<li key={i}>{hobby}</li>
)
})}
</ul>
</div>
</div>
</div>
</div>
)
})}
</div>
</div>
)
}
请注意,每个人的信息都是一个额外的类,.info
目的是在我的两列之间添加一些额外的对齐和间距。
总结
感谢您阅读我对 Flexbox 的分析,我希望您对如何使用 flex 属性来提高您的 CSS 布局和设计技能更有信心!
一如既往,我期待收到反馈和建设性批评。我相信自己还有很多地方可以学习和改进。如果您发现我可以改进或解释得更好,请在评论区告诉我!
再次感谢并祝您编码愉快!
鏂囩珷鏉ユ簮锛�https://dev.to/jamesncox/flexbox-rocks-2bf9