vux flexbox使用
是时候在flexbox中进行实际练习了! 在本教程中,我们将使用flexbox创建针对移动设备,平板电脑和台式机屏幕的移动优先,可响应,可切换的导航栏,并具有不同的布局。
注意 :本教程已更新,包括响应式子菜单和纯JavaScript而不是jQuery。
Flexbox非常适合响应式导航
Flexbox是一个通用的布局模块,通过它我们可以创建需要灵活性的一维布局,例如响应菜单。 使用flexbox的ordering,alignment和sizing属性,我们可以构建导航栏,以使其布局适应视口大小,同时保持HTML轮廓线的逻辑性和可访问性。
在本教程中,我们将研究如何使用flexbox创建响应式导航栏。 我们的flexbox导航将具有三种不同的布局,具体取决于视口的大小:
- 在默认情况下仅徽标和切换按钮可见的移动布局中,用户可以使用切换按钮来打开和关闭菜单,
- 平板电脑的布局,在该布局中,我们将在徽标之间显示两个号召性用语按钮,并在默认状态下进行切换,其余菜单仍保持可切换状态,
- 一种桌面布局 ,其中所有菜单项(切换按钮除外)都将在屏幕上可见。
我们将使用媒体查询来检测用户浏览器的视口大小。 我们的响应式导航栏将是移动优先的,因此我们将首先创建移动布局。 然后,我们将使用min-width媒体查询添加特定于平板电脑和台式机CSS。
导航栏还将具有一个基于JavaScript的下拉子菜单,当用户单击父菜单项时,该子菜单将打开和关闭。
菜单在移动设备上的外观如下:
这是平板电脑版本:
而且,这是它在桌面上的外观:
您还可以在CodePen上测试,派生和玩交互式演示:
刚接触Flexbox?
1.创建HTML
HTML是一个简单的<ul>列表,如下所示。 .menu类将是flex容器,列表项将是flex项。 它们的顺序将适应用户设备的视口大小。 例如,“ 登录”和“ 注册”按钮将首先出现在移动设备上,但将显示在桌面上菜单的末尾。 我们将通过使用flexbox的ordering属性来实现这种效果。
<nav>
<ul class="menu">
<li class="logo"><a href="#">Creative Mind Agency</a></li>
<li class="item"><a href="#">Home</a></li>
<li class="item"><a href="#">About</a></li>
<li class="item has-submenu">
<a tabindex="0">Services</a>
<ul class="submenu">
<li class="subitem"><a href="#">Design</a></li>
<li class="subitem"><a href="#">Development</a></li>
<li class="subitem"><a href="#">SEO</a></li>
<li class="subitem"><a href="#">Copywriting</a></li>
</ul>
</li>
<li class="item has-submenu">
<a tabindex="0">Plans</a>
<ul class="submenu">
<li class="subitem"><a href="#">Freelancer</a></li>
<li class="subitem"><a href="#">Startup</a></li>
<li class="subitem"><a href="#">Enterprise</a></li>
</ul>
</li>
<li class="item"><a href="#">Blog</a></li>
<li class="item"><a href="#">Contact</a>
</li>
<li class="item button"><a href="#">Log In</a></li>
<li class="item button secondary"><a href="#">Sign Up</a></li>
<li class="toggle"><a href="#"><i class="fas fa-bars"></i></a></li>
</ul>
</nav>
您可能已经注意到带有子菜单(“服务”和“计划”)的菜单项具有<a>标记,而没有href属性。 我们这样做是因为这些“空”父菜单项不会导致任何其他页面,它们只是打开和关闭子菜单。 允许在不使用href的情况下使用定位标记,并且当用户单击空白菜单项打开或关闭子菜单时,可以防止页面在小屏幕上跳转。
我们还将tabindex="0"属性添加到没有href属性的<a>元素中。 这是因为空<a>标记从默认制表符顺序中省略了,因此我们需要使用tabindex属性将它们放回制表符顺序,以使菜单键盘可访问 。
注意 :列表末尾的切换按钮使用“真棒字体”图标。 为了使演示工作正常进行,您需要使用下面的代码将Font Awesome库添加到CDNHTML文档的<head>部分中。 (如果要使菜单脱机工作,则需要在本地托管Font Awesome 。)
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
2.添加一些基本样式
对于基本样式,我设置了一些默认值和颜色,但是您也可以使用任何自己的样式规则:
/* Basic styling */
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: sans-serif;
font-size: 16px;
}
nav {
background: #222;
padding: 0 15px;
}
a {
color: white;
text-decoration: none;
}
.menu,
.submenu {
list-style-type: none;
}
.logo {
font-size: 20px;
padding: 7.5px 10px 7.5px 0;
}
.item {
padding: 10px;
}
.item.button {
padding: 9px 5px;
}
.item:not(.button) a:hover,
.item a:hover::after {
color: #ccc;
}
3.从移动导航开始
由于导航将是移动优先,因此我们从移动布局开始。 大多数响应式flexbox菜单都使用基于列的移动版布局,因为可以通过添加flex-direction: column;来快速将菜单项包装在彼此之间flex-direction: column; 统治弹性容器。 即使这是一个出色的解决方案,我们也不会在示例中使用它。
相反,我们将为移动设备创建一个基于行的环绕式布局,以便我们可以在菜单顶部彼此相邻显示徽标和切换按钮。
这里CSS技巧是,我们使用width: 100%;来使常规菜单项(例如Home和About)跨整个容器width: 100%; 规则。 因此,flexbox将它们显示在彼此下方,而徽标和切换按钮将保留其自然大小,并位于导航栏中同一行的顶部。
在下面CSS中,我们还使用justify-content和align-items属性将flex项目水平和垂直对齐 。 除此之外,我们使用display: none;隐藏.item元素display: none; 规则。 菜单项仅在用户单击切换按钮时显示。 .active类不在HTML代码中,我们将使用JavaScript动态添加它。
/* Mobile menu */
.menu {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.menu li a {
display: block;
padding: 15px 5px;
}
.menu li.subitem a {
padding: 15px;
}
.toggle {
order: 1;
font-size: 20px;
}
.item.button {
order: 2;
}
.item {
order: 3;
width: 100%;
text-align: center;
display: none;
}
.active .item {
display: block;
}
.button.secondary { /* divider between buttons and menu links */
border-bottom: 1px #444 solid;
}
正如您在上面看到的,我们还通过order属性更改了菜单项的order 。 我们HTML大纲遵循逻辑顺序。 这就是我们希望屏幕阅读器用户和搜索引擎机器人通过菜单进行浏览的方式。
但是,在移动版式中,我们要在菜单顶部显示徽标和切换按钮。 我们还希望在常规菜单项之前显示两个号召性用语按钮(“登录”和“注册”)。 因此,我们建立了以下顺序:
-
.logo的order: 0;值,因为它将是第一项(但是,因为这是order的默认值,我们不需要将其添加到CSS), -
.toggle得到1,因为它.logo之后, - 属于“ 登录”和“ 注册”按钮的
.item.button获得2, - 属于其余菜单项的
.item变为3。
4.设置子菜单的样式
由于这是移动优先导航,因此我们首先会考虑移动屏幕来设置子菜单的样式。 这是一项很棒的技术,因为为小屏幕创建一个用户友好的子菜单通常要比为大屏幕创建子菜单更为困难。 然后,我们也可以为平板电脑屏幕使用相同的子菜单布局。 对于台式机,我们只需要更改子菜单的位置。
默认情况下,子菜单设置为display: none; 并且仅在用户单击父菜单项时才会显示。 在进入平板电脑菜单之前,我们将在接下来的两个步骤中添加所需JavaScript功能。
/* Submenu up from mobile screens */
.submenu {
display: none;
}
.submenu-active .submenu {
display: block;
}
.has-submenu i {
font-size: 12px;
}
.has-submenu > a::after {
font-family: "Font Awesome 5 Free";
font-size: 12px;
line-height: 16px;
font-weight: 900;
content: "\f078";
color: white;
padding-left: 5px;
}
.subitem a {
padding: 10px 15px;
}
.submenu-active {
background-color: #111;
border-radius: 3px;
}
如您在上面看到的,现在我们使用CSS而不是HTML添加Font Awesome图标。 我们使用::after伪元素添加的这些图标将是带有子菜单的每个菜单项旁边显示的小向下箭头 。
如果您还记得我们在步骤1中使用HTML为切换按钮添加了Font Awesome图标,这是因为该切换按钮将以JavaScript为目标,因此它必须出现在DOM中。 但是,这里的向下箭头只是样式元素,表示子菜单的存在。 由于没有功能依赖于它们,因此最好使用CSS添加它们。
5.使用JavaScript添加Toggle功能
我们将通过在点击按钮中添加点击事件监听器来设置切换功能,以打开和关闭移动设备上的菜单。 在JavaScript代码中,我们将使用ES6语法,该语法使我们可以访问const和let表示法以及for...of循环,并且已经具有良好的浏览器支持 。
对于自定义JavaScript,请创建一个空的script.js文件,并将其添加到</body>标记之前HTML中:
<script src="script.js"></script>
这是负责切换功能的JavaSript代码:
const toggle = document.querySelector(".toggle");
const menu = document.querySelector(".menu");
/* Toggle mobile menu */
function toggleMenu() {
if (menu.classList.contains("active")) {
menu.classList.remove("active");
// adds the menu (hamburger) icon
toggle.querySelector("a").innerHTML = "<i class=’fas fa-bars’></i>";
} else {
menu.classList.add("active");
// adds the close (x) icon
toggle.querySelector("a").innerHTML = "<i class=’fas fa-times’></i>";
}
}
/* Event Listener */
toggle.addEventListener("click", toggleMenu, false);
- 首先,我们使用
querySelector()方法选择菜单和切换按钮 ,以便我们可以使用JavaScript访问它们。 - 然后,我们添加自定义
toggleMenu()函数,该函数将在单击切换按钮时调用。 - 最后,我们使用
addEventListener()方法添加事件监听器,该监听器将监听click事件。
6.使用JavaScript添加下拉功能
现在,当用户单击切换按钮时,菜单被激活和停用,但是,子菜单仍处于隐藏状态。 我们将使用以下JavaScript添加此功能:
const items = document.querySelectorAll(".item");
/* Activate Submenu */
function toggleItem() {
if (this.classList.contains("submenu-active")) {
this.classList.remove("submenu-active");
} else if (menu.querySelector(".submenu-active")) {
menu.querySelector(".submenu-active").classList.remove("submenu-active");
this.classList.add("submenu-active");
} else {
this.classList.add("submenu-active");
}
}
/* Event Listeners */
for (let item of items) {
if (item.querySelector(".submenu")) {
item.addEventListener("click", toggleItem, false);
item.addEventListener("keypress", toggleItem, false);
}
}
在这里,当用户单击时,我们将.submenu-active类添加到带有子菜单的每个菜单项 。
- 首先,我们使用
querySelectorAll()方法选择所有菜单项,该方法返回节点列表(而不是单个元素,例如querySelector())。 - 在自定义
toggleItem()函数中,我们向/从单击的元素添加和删除.submenu-active。 注意,在else if块中,我们从以前打开的所有其他菜单项中删除该类。 这样,两个子菜单不会同时打开,因为它们可以在桌面上相互覆盖。 - 最后,我们使用
for...of循环遍历classListitems。 在if块中,我们将两个事件侦听器添加到具有子菜单的菜单项:一个用于通过单击或点击访问菜单的普通用户的click事件,一个用于键盘用户的keypress事件。
7.创建平板电脑菜单
我们将使用min-width媒体查询创建平板电脑布局。 在平板电脑上,默认情况下会显示四个菜单项:徽标,两个号召性用语按钮(“登录”和“注册”)以及切换键。 为了使所有内容漂亮,我们CSS将:
- 更改菜单项的
order以使布局适合平板电脑视口, - 重新调整项目(请参见以下说明),
- 使“ 登录”和“ 注册”按钮看起来像真实按钮(在移动布局中,它们看起来像链接,因为它们是可切换下拉列表的一部分)。
在代码中:
/* Tablet menu */
@media all and (min-width: 700px) {
.menu {
justify-content: center;
}
.logo {
flex: 1;
}
.item.button {
width: auto;
order: 1;
display: block;
}
.toggle {
flex: 1;
text-align: right;
order: 2;
}
/* Button up from tablet screen */
.menu li.button a {
padding: 10px 15px;
margin: 5px 0;
}
.button a {
background: #0080ff;
border: 1px royalblue solid;
}
.button.secondary {
border: 0;
}
.button.secondary a {
background: transparent;
border: 1px #0080ff solid;
}
.button a:hover {
text-decoration: none;
}
.button:not(.secondary) a:hover {
background: royalblue;
border-color: darkblue;
}
}
在数位板布局中,菜单项以不同的方式对齐。 如果看一下四个可见的菜单项,将会看到两个按钮显示在中间,而徽标和切换按钮则被推到了容器的左右两端:
我们可以使用flex: 1;实现此效果flex: 1; CSS规则。 flex属性是flex-grow , flex-shrink和flex-basis的简写。 它可以存在许多不同的值组合。 当仅声明一个值时,它属于flex-grow ,而flex-shrink和flex-basis保留其默认值。
在上面CSS中,我们添加了flex: 1; .logo和.toggle元素的规则。 通过这种方式,我们可以告诉浏览器,如果屏幕上存在正空间,我们希望在这两个元素之间共享它。 由于“ 登录”和“ 注册”按钮保留其flex-grow的默认0值,因此它们不会从多余的空间中得到任何东西。 因此,由于它们遵循justify-content: center; ,因此它们将保持在容器的justify-content: center; 在flex容器上设置规则。
8.创建桌面菜单
桌面菜单隐藏该切换开关,重新设置每个项目的原始顺序和自然宽度,然后重新定位子菜单。
重要的是要记住,数位板特定的规则也适用于桌面菜单。 这是因为在此,视口宽度大于700px和960px ,因此两个媒体查询均生效。 因此, .logo保留其flex: 1; 属性,并将其余项目推到容器的末尾。
/* Desktop menu */
@media all and (min-width: 960px) {
.menu {
align-items: flex-start;
flex-wrap: nowrap;
background: none;
}
.logo {
order: 0;
}
.item {
order: 1;
position: relative;
display: block;
width: auto;
}
.button {
order: 2;
}
.submenu-active .submenu {
display: block;
position: absolute;
left: 0;
top: 68px;
background: #111;
}
.toggle {
display: none;
}
.submenu-active {
border-radius: 0;
}
}
9.让用户通过单击页面上的任意位置来关闭子菜单
现在只有退后一步。 由于在单击事件上激活了下拉菜单,因此当用户将鼠标悬停在顶部菜单项上时,它不会自动关闭。 在桌面可以覆盖内容的桌面上,这尤其令人讨厌。
因此,最好使用户能够通过单击屏幕上的任意位置来关闭子菜单。 我们可以使用JavaScript添加该功能:
/* Close Submenu From Anywhere */
function closeSubmenu(e) {
let isClickInside = menu.contains(e.target);
if (!isClickInside && menu.querySelector(".submenu-active")) {
menu.querySelector(".submenu-active").classList.remove("submenu-active");
}
}
/* Event listener */
document.addEventListener("click", closeSubmenu, false);
定制的closeSubmenu()函数检查用户是否在target属性的帮助下单击了菜单内的内容。 如果不是,并且屏幕上有一个活动子菜单,则将删除.submenu-active类,因此该子菜单会自行关闭。 我们想将事件监听器添加到document对象中,因为我们想监听整个页面上的点击。
您已经使用Flexbox和JavaScript构建了响应式导航栏!
我们的移动优先响应式导航栏以三种不同的布局启动并运行。
这是对最终结果的提醒:
Flexbox是实现复杂布局而无需进行任何调整的好工具。 如果将flexbox的alignment,ordering和sizing属性与媒体查询结合使用,则可以为不同的视口创建不同的布局,而无需操纵HTML源代码。
有用的资源
vux flexbox使用
本文详细介绍了如何使用Flexbox和JavaScript构建移动优先的响应式导航栏,涵盖不同设备布局,包括移动、平板和桌面。通过媒体查询、CSS样式和JavaScript交互功能,实现子菜单的显示和关闭,提供良好的用户体验。
203

被折叠的 条评论
为什么被折叠?



