Github 地址 (可查看交互效果)css
切图的三个境界:html
给不一样页面添加不一样类,标识不一样页面,而后设置当前页面样式,覆盖掉默认样式。前端
代码:css3
<div class="demo1"> <ul class="nav"> <li class="nav-item item-home">首页</li> <li class="nav-item item-demo1">导航高亮</li> </ul> </div>
.nav { padding: 5px 10px; background: #000; color: #fff; } .nav .nav-item { display: inline-block; margin-right: 10px; list-style: none; opacity: 0.5; cursor: pointer; &:hover { opacity: 1; } } .demo1 .nav.nav-item.item-demo1 { opacity: 1; }
本身的想法:这种方式虽然好,可是,须要为每一个导航都写一个默认和高亮样式,若是不是同一我的写的代码,在新增导航的时候,很容易会忘记去加上。git
看到后面的时候,发现书中有这个问题相关的回答,能够用 sass 进行 for 循环实现。同时,还能够定义主题色变量。github
hover 到某个菜单时,显示子菜单。sass
代码:less
<!-- html --> <div class="demo2"> <ul class="nav"> <li class="nav-item item-home">首页</li> <li class="nav-item item-demo1">导航高亮</li> <li class="menu"> <ul> <li>导航高亮-下级1</li> <li>导航高亮-下级2</li> </ul> </li> <li class="nav-item item-demo2">导航悬浮显示下级</li> <li class="menu"> <ul> <li>导航悬浮显示下级-下级1</li> <li>导航悬浮显示下级-下级2</li> </ul> </li> </ul> </div>
// less .nav { position: relative; padding: 5px 10px; background: #06a992; color: #fff; } .nav .nav-item { display: inline-block; margin-right: 10px; list-style: none; opacity: 0.5; cursor: pointer; &:hover { // <-- 在导航菜单上须要加 hover opacity: 1; } } .demo2 .nav .nav-item.item-demo2 { opacity: 1; } .nav-item:hover + .menu{ display: list-item; } .menu { display: none; position: absolute; top: 44px; min-width: 100px; color: #000; border: 1px solid #000; box-shadow: 0 0 5px; &:before { // <-- 加一个伪元素,能够避免当下拉列表和导航菜单名称之间有空隙时,鼠标往下移到下拉列表的过程当中,脱离导航菜单名称而隐藏下拉列表的状况 content: ""; position: absolute; left: 0; top: -20px; width: 100%; height: 20px; } &:hover { // <-- 隐藏元素自己也须要加 hover display: list-item; } } ul, ul li { list-style: none; }
本身的想法:书中提到,能够经过 absolute 给 .menu 定位,我想了很久,都想不出来怎么实现,若是有实现方法的,请告知,谢谢!布局
对上面的 demo 作了布局的改变,如今能够简单的经过 absolute 来定位了,参考:flex
代码:
<!-- html --> <div class="demo2"> <nav> <ul class="nav-ul"> <li class="nav-item item-home">首页</li> </ul> <ul class="nav-ul"> <li class="nav-item item-demo1">导航高亮</li> <li class="menu"> <ul class="menu-ul"> <li>导航高亮-下级1</li> <li>导航高亮-下级2</li> </ul> </li> </ul> <ul class="nav-ul"> <li class="nav-item item-demo2">导航悬浮显示下级</li> <li class="menu"> <ul class="menu-ul"> <li>导航悬浮显示下级-下级1</li> <li>导航悬浮显示下级-下级2</li> </ul> </li> </ul> </nav> </div>
// less nav { font-size: 0; } .nav-ul { display: inline-block; position: relative; padding: 5px 10px; font-size: 16px; background: #06a992; color: #fff; } .nav-ul .nav-item { display: inline-block; margin-right: 10px; list-style: none; opacity: 0.5; cursor: pointer; &:hover { opacity: 1; } } .demo2 .nav-ul .nav-item.item-demo2 { opacity: 1; } .nav-item:hover + .menu{ display: list-item; } .menu { display: none; position: absolute; top: 44px; min-width: 100px; white-space: nowrap; color: #000; border: 1px solid #000; box-shadow: 0 0 5px; &:before { // <-- 加一个伪元素,能够避免当下拉列表和导航菜单名称之间有空隙时,鼠标往下移到下拉列表的过程当中,脱离导航菜单名称而隐藏下拉列表的状况 content: ""; position: absolute; left: 0; top: -20px; width: 100%; height: 20px; } &:hover { display: list-item; } .menu-ul { padding-right: 1.2em; } } ul, ul li { list-style: none; }
代码:
<template> <div class="demo2"> <nav> <ul class="nav-ul"> <li class="nav-item item-home">首页</li> </ul> <ul class="nav-ul" @mouseover="showSubmenu = true" @mouseout="showSubmenu = false"> <li class="nav-item item-demo1">导航高亮</li> <li class="menu" :style="{ display: showSubmenu ? 'block' : 'none' }"> <ul class="menu-ul"> <li>导航高亮-下级1</li> <li>导航高亮-下级2</li> </ul> </li> </ul> <ul class="nav-ul"> <li class="nav-item item-demo2">导航悬浮显示下级</li> <li class="menu"> <ul class="menu-ul"> <li>导航悬浮显示下级-下级1</li> <li>导航悬浮显示下级-下级2</li> </ul> </li> </ul> </nav> </div> </template> <script> export default { name: 'demo-nav-hover-show1', data() { return { showSubmenu: false, // <-- 代码仅做为演示用 }; }, }; </script>
能够看到,加了 mouse 事件后,鼠标悬浮后,会在元素的 style 中加上 display: none;
,致使 css 中的样式失效:
意外状况:移动端 Safari 上,触摸会触发 CSS 的 hover,hover 会很高几率地先于 touchstart 事件,此时会判断当前是显示仍是隐藏状态,因为 CSS 的 hover 发挥了做用,因此判断为显示,而后又把它隐藏了。也就是说,点一次不出来,要点两次。因此最好别两个同时写。
代码:
<div class="demo"> <ul class="nav"> <li class="nav-item item-home"> <span>首页</span> </li> <li class="nav-item item-demo"> <span>鼠标悬浮显示下级下拉菜单</span> <ul class="menu-ul"> <li>导航悬浮显示下级-下级1</li> <li>导航悬浮显示下级-下级2</li> </ul> </li> </ul> </div>
.nav { padding: 5px 10px; background: #06a992; color: #fff; } .nav .nav-item { position: relative; display: inline-block; margin-right: 10px; list-style: none; opacity: 0.5; cursor: pointer; &:hover { opacity: 1; .menu-ul { display: block; } } } .demo .nav .nav-item.item-demo { opacity: 1; } .menu-ul { display: none; position: absolute; left: 0; top: 44px; min-width: 100px; padding-right: 1.2em; white-space: nowrap; border: 1px solid #000; box-shadow: 0 0 5px; color: #000; background-color: #fff; &:before { // <-- 加一个伪元素,能够避免当下拉列表和导航菜单名称之间有空隙时,鼠标往下移到下拉列表的过程当中,脱离导航菜单名称而隐藏下拉列表的状况 content: ""; position: absolute; left: 0; top: -20px; width: 100%; height: 20px; } } ul, ul li { list-style: none; }
使用子元素的话,hover 可直接加在父容器上,隐藏元素自己不须要加 hover。
可使用 :checked 代替鼠标点击事件。
代码:
<!--html--> <div class="radio-checkbox"> <label class="control-label"> <input type="radio" value="value1" name="radio"> radio1: <span class="radio"></span> </label> <label class="control-label"> <input type="radio" value="value2" name="radio"> radio2: <span class="radio"></span> </label> <label class="control-label"> <input type="checkbox" value="value1"> checkbox <span class="checkbox"></span> </label> </div>
// less input[type=checkbox], input[type=radio] { display: none; } .control-label { margin-right: 10px; display: inline-block; cursor: pointer; } .radio { position: relative; display: inline-block; width: 16px; height: 16px; vertical-align: middle; border: 1px solid #3eaf7c; border-radius 50%; } input[type=radio]:checked + .radio { box-shadow: 0 0 3px #3eaf7c; &:after { content: ''; width: 50%; height: 50%; display: block; position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); background: #3eaf7c; border-radius 50%; } } .checkbox { position: relative; display: inline-block; width: 16px; height: 16px; vertical-align: middle; border: 1px solid #3eaf7c; } input[type=checkbox]:checked + .checkbox { box-shadow: 0 0 3px #3eaf7c; &:after { content: '✓'; display: block; position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); color: #3eaf7c; } }
使用 :checked 属性时,要注意兼容性:
设置一个很大的 padding-bottom,这样容器被最大的子元素撑开时,其余的子元素使用能够用 padding-bottom 来补偿缺乏的高度。而后设置一个同方向的 margin-bottom 负值,能够抵消设置的 padding-bottom。 同时设置父容器的 overflow: hidden;
,将多余的部分裁剪(隐藏)掉。
代码:
<!--html--> <div class="demo"> <div class="col col1"> <p class="title">苹果</p> <p class="des"> 苹果,是水果中的一种,是蔷薇科苹果亚科苹果属植物,其树为落叶乔木。 </p> </div> <div class="col col2"> <p class="title">香蕉</p> <p class="des"> 香蕉(学名:Musa nana Lour.)芭蕉科芭蕉属植物,又指其果实,热带地区普遍种植。 </p> </div> <div class="col col3"> <p class="title">水蜜桃</p> <p class="des"> 水蜜桃(学名:Prunus persica 、meltingfleshed peach):蔷薇科、桃属植物。南方品种群中肉质柔软多汁呈软溶质的一类品种。果实顶部平圆,熟后易剥皮,多粘核。 </p> </div> <div class="col col4"> <p class="title">菠萝</p> <p class="des"> 菠萝(学名:Ananas comosus),是热带水果之一。 </p> </div> </div>
// less .demo { overflow: hidden; } .col { float: left; width: 20%; padding-top: 10px; padding-left: 10px; padding-right: 10px; padding-bottom 2000px; // <-- 设置 padding-bottom margin-bottom: -2000px; // <-- 设置 margin-bottom margin-right: 10px; border: 1px solid #000; border-radius: 5px; }
缺点:底部的 border 没有了,底部圆角也不显示了。
table 中的每一个 td 都是等高的,因此能够设置容器 display: table;
,设置里面的子元素 display: table-cell;
。将子元素的宽度设大点,能够实现等分。
代码:
// stylus
.demo
display table
border-spacing 20px // <-- 设置间隔
word-break break-all
.col
display table-cell
width 1000px // <-- 设置很大的宽度,table 自动平分宽度
padding: 10px
border 1px solid #000
border-radius 5px
注意:虽然 table 布局能够实现等分,可是有一种状况须要注意,就是英文单词很长,没有设置 word-break 的时候,这种状况是不会自动等分的。
这种布局的另外一个好处,就是能够在媒体查询时,实现响应式。
能够尝试拉伸屏幕,观察下面的布局变化。(大屏显示每行四列,中屏显示每行两列,小屏显示每行一列。)
代码:
<!--html--> <div class="demo"> <div class="col col1"> <p class="title">苹果</p> <p class="des"> 苹果,是水果中的一种,是蔷薇科苹果亚科苹果属植物,其树为落叶乔木。 </p> </div> <div class="col col2"> <p class="title">香蕉</p> <p class="des"> 香蕉(学名:Musa nana Lour.)芭蕉科芭蕉属植物,又指其果实,热带地区普遍种植。 </p> </div> <!--加了个 tr 实现一行两列布局--> <span class="tr"></span> <div class="col col3"> <p class="title">水蜜桃</p> <p class="des"> 水蜜桃(学名:Prunus persica 、meltingfleshed peach):蔷薇科、桃属植物。南方品种群中肉质柔软多汁呈软溶质的一类品种。果实顶部平圆,熟后易剥皮,多粘核。 </p> </div> <div class="col col4"> <p class="title">菠萝</p> <p class="des"> 菠萝(学名:Ananas comosus),是热带水果之一。 </p> </div> </div>
// stylus
.demo
display table
border-spacing 20px // <-- 设置间隔
word-break break-all
.col
display table-cell
width 1000px // <-- 设置很大的宽度,table 自动平分宽度
padding: 10px
border 1px solid #000
border-radius 5px
.tr
display none
@media (max-width: 500px)
.demo
display block // <-- 能够覆盖原来的样式,实现响应式布局
.col
display block // <-- 能够覆盖原来的样式,实现响应式布局
width: 100%
@media (max-width: 1024px) and (min-width: 501px)
.tr
display table-row // <-- 实现一行两列布局
能够看到,从一行两列布局拉伸到宽屏时,.tr 的 display: none;
不起做用了。由于 table 布局已经计算好了。要解决这个问题,须要借助 JavaScript。
代码:
<!--html--> <div class="demo"> <div class="col col1"> <p class="title">苹果</p> <p class="des"> 苹果,是水果中的一种,是蔷薇科苹果亚科苹果属植物,其树为落叶乔木。 </p> </div> <div class="col col2"> <p class="title">香蕉</p> <p class="des"> 香蕉(学名:Musa nana Lour.)芭蕉科芭蕉属植物,又指其果实,热带地区普遍种植。 </p> </div> <div class="col col3"> <p class="title">水蜜桃</p> <p class="des"> 水蜜桃(学名:Prunus persica 、meltingfleshed peach):蔷薇科、桃属植物。南方品种群中肉质柔软多汁呈软溶质的一类品种。果实顶部平圆,熟后易剥皮,多粘核。 </p> </div> <div class="col col4"> <p class="title">菠萝</p> <p class="des"> 菠萝(学名:Ananas comosus),是热带水果之一。 </p> </div> </div>
// less .demo { display: flex; word-break break-all .col { width: 25%; padding: 10px; margin: 0 10px; border: 1px solid #000; border-radius: 5px; } }
需求:
例若有 1 ~ 3 个 item 显示在同一行,但 item 的个数不必定,若是只有 1 个,那 item 占宽 100%;若是有 2 个,每一个占 50%;若是有 3 个,每一个占 33%。
:nth-last-child(an+b) 这个 CSS 伪类匹配文档树中在其以后具备 an+b-1 个兄弟节点的元素,其中 n 为正值或零值。它基本上和 :nth-child 同样,只是它从结尾处反序计数,而不是从开头处。MDN
代码:
<!--html--> <div class="demo"> <ul class="list clearfix"> <li class="list-item">一行 1 个</li> </ul> <ul class="list clearfix"> <li class="list-item">一行 2 个</li> <li class="list-item">一行 2 个</li> </ul> <ul class="list clearfix"> <li class="list-item">一行 3 个</li> <li class="list-item">一行 3 个</li> <li class="list-item">一行 3 个</li> </ul> </div>
// less .demo { width: 100%; .list { .list-item { display: inline-block; float: left; text-align: center; border: 1px solid #000; box-sizing: border-box; // <-- 设置 box-sizing background-color: #4abf8a; &:nth-child(2) { background-color: #3a8ee6; } &:nth-child(3) { background-color: yellow; } width: 100%; // <-- 一行显示一个时,使用该样式 &:first-child:nth-last-child(2), &:first-child:nth-last-child(2) ~ .list-item { // <-- 一行显示两个时,使用该样式,&:first-child:nth-last-child(2) 指向第一个元素 width: 50%; } &:first-child:nth-last-child(3), &:first-child:nth-last-child(3) ~ .list-item { // <-- 一行显示两个时,使用该样式,&:first-child:nth-last-child(2) 指向第一个元素 width: 33.3%; } } } }
须要注意的是,若是 item 有 border,这样设置是不行的,由于 border 也会占据必定的宽度。设置一下 box-sizing: border-box; 便可。
需求:
手机屏幕比较小,左边图标比较多,一行排不下,把右边的电话换行,隐藏竖线。(左边图标个数不定)
感受需求描述不完整,想象不出这种场景,没法实现代码。
代码:
<!--html--> <form class="form"> <p>利用 :focus 伪类实现 focus 时,放大镜颜色加深。</p> <div class="form-group"> <label for="search" class="form-label"></label> <div class="form-control"> <input class="form-control-input" id="search" type="text"> <i class="icon-search fas fa-search"></i> </div> </div> <p>利用 :invalid 伪类进行校验。</p> <div class="form-group"> <label for="email" class="form-label"></label> <div class="form-control"> <input class="form-control-input" id="email" type="email"> <span class="btn">Next</span> </div> </div> </form>
// less .form-control { position: relative; } .form-control-input { padding: 0 32px; &:focus + .icon-search { // <-- :focus 伪类 color: #3eaf7c; } &:invalid + .btn { // <-- :invalid 伪类 opacity: .5; cursor: default; } } .icon-search { position: absolute; left: 10px; top: 14px; color: #ddd; } .btn { height: 40px; line-height: 1.5; padding: 5px 10px; position: absolute; right: 0; top: 0; transform: translateX(100%); border: 1px solid #3eaf7c; border-radius: 3px; background: #3eaf7c; color: #fff; cursor: pointer; }
需求:
hover 时显示提示信息。不想用 title,也不想用 JavaScript,更不想引入第三方库。
代码:
<!--html--> <p> Hello <span class="tip" data-title="Frontend Development">FED</span> </p>
// less .tip { position: relative; &:hover:before { padding: 5px; content: attr(data-title); position: absolute; left: 50%; top: -230%; transform: translateX(-50%); white-space: nowrap; border-radius: 5px; background: #000; color: #fff; } &:hover:after { position: absolute; top: -10px; left: 50%; transform: translateX(-50%); content: ''; width: 0; height: 0; border-style: solid; border-width: 12px; border-color: transparent; border-top-color: #000; } }