a标签中具有开始标签和结束标签;
a标签中可以写行内元素、行内块元素、块元素;
a标签中如果包裹一张图片(图片属于替换元素,具有行内块元素特点),此时,整个图片可点击,但是a标签的高度仍然相当于是行内元素;但是如果把图片的display改为block,此时,a标签就与图片等高(消除了底下的空隙),并且底部对齐,并且,此时,a元素就成了块元素;
行内元素中,一般只有a元素中,才会去嵌套块元素;
一个div中包含一个a标签,这个a标签又包含一个div,里面这个div如果设置高度和宽度为百分比,相对的是a标签外面的这个div的宽高,好像就略过了a标签一样;
一个div中包含一个a标签,div有指定大小,然后让a标签水平居中,使用text-align:center,然后a标签可以使用margin-left或margin-right或padding-left或padding-right移动a标签的位置,垂直方向上移不了,只能水平方向。
body {
cursor: url(./default.cur),default;
}
处理行内块元素的空白字符折叠(行内块元素的结束标签和另外一个行内块元素结束标签在源码中没有紧紧的挨着,默认情况下,中间的多个空白字符会被视为一个空白字符)
.list {
font-size: 0;
letter-spacing: -.31em;
}
块级元素中使用white-space:nowrap 可以让块级元素内部的行内块元素不换行,即让这些行内块元素同一行显示,哪怕超出父元素宽度
.container {
width: 300px;
line-height: 0;
letter-spacing: -0.31em;
}
.box1 {
height: 100px;
width: 100px;
background-color: #bfa;
display: inline-block;
}
.item-list {
text-align: justify;
}
.item-list::after {
content: '';
display: inline-block;
width: 100%;
}
object-fit取值说明
object-fit主要适合于替换元素,比如:
fill:此值为boject-fit的默认值,替换内容的大小被设置为填充元素的内容框,也就是说,元素的内容扩大到完全填充容器的外形尺寸,即使这打破其内在的宽高比。
contain:替换元素内容大小保持长宽比例填充元素内容容器,其具体对象大小被解析为一个包含元素的宽度和高度。也就是说,如果你在替换元素上设置一个明确的高度和宽度,此值将导致内容大小,完全在固定的比例显示,但仍在元素尺寸内显示,并且会默认居中。
cover:替换元素内容大小保持长宽比例填充元素内容容器,其具体对象大小被解析为覆盖整个元素的宽度和高度。也就是说,替换元素内容大小保持长宽比,但改变宽度和高度,以便完全覆盖内容元素,并且会默认居中。
none:替换元素内容不调整大小以适应内部元素的容器,内容完全忽略设置在元素上的任何高度和权重,并且仍在元素尺寸内显示。
scale-down:当内容大小设置了non或contain,将导致具体对象变得更小。
.box {
margin-top: 80px;
margin-left: 400px;
display: flex;
width: 100px;
height: 100px;
overflow: hidden;
align-items: center;
justify-content: center;
background-color: #bfa;
}
img {
width: 100%;
/* height: 100% */
}
"box">
"./02_flex/img/d1.jpg" alt="">
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.container {
display: flex;
width: 200px;
height: 200px;
border: 1px solid red;
align-items: center;
justify-content: center;
position: relative;
}
.container .box1,.container .span1 {
position: absolute;
}
style>
head>
<body>
<div class="container">
<div class="box1">box1box1box1div>
<span class="span1">span1span>
div>
body>
html>
下面这个示例中,是这里描述的一个应用场景,也可以用于有其它需要的类似场景。这种方式 和 使用 calc 来控制高度有异曲同工之妙,用calc的实现也差不多。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
body {
margin: 0;
}
.app {
/* 最小高度将占满可视窗口
- 也就是说,如果main的由于内容少,而高度不够,那么.app的高度将取屏幕的高度,这样main由于flex-grow:1自动扩展,高度将会占满所有高度
- 如果main的内容很多,多到超过屏幕高度,那没关系,main仍然占据所有高度
*/
min-height: 100vh;
background-color: #ccc;
display: flex;
flex-direction: column;
}
.main {
background-color: #bfa;
flex: 1 0 auto;
/* 头部和footer都可以塞到上下2个padding里面去做固定定位 */
padding-top: 60px;
padding-bottom: 160px;
}
style>
head>
<body>
<div class="app">
<div class="main">div>
div>
body>
html>
步骤:父元素开启flex布局,默认主轴方向为水平方向,aligh-items默认为stretch。当子元素设置flex:1 1 auto时,子元素就有了宽度并且占满所有宽度,由于aligh-items默认为stretch,自然能占满整个高度,也就是宽高都占满了父元素。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.box1 {
width: 300px;
height: 300px;
background-color: #ccc;
display: flex;
/* align-items: stretch; */ /* 默认值,可以不需要写 */
}
.box2 {
background-color: pink;
flex: 1 1 auto;
}
style>
head>
<body>
<div class="box1">
<div class="box2">div>
div>
body>
html>
min-height的使用分析:整个body上下两个div(div1和div2),div2的高度设置为固定的60px,div1的高度设置为min-height:(100vh - 60px),div1在上面。div1设置这个值后,相当于就是说,div1的高度始终要>=100vh-60px,也就意味着,div1至少应该要占满div2以上的全部空间的高度。当div1中的子元素累积高度少于100vh-60px时候,div的高度本来应当与子元素高度保持一致,但是由于设置了min-height,就直接取得100vh-60px。当div1的子元素累积高度大于100vh-60px时,显然div1加上div2的高度要大于100vh了,因此会出现滚动条
div下面套了一个a标签,a标签里面又套了一个图片。当设置图片的宽度或高度为100%时候,相对的高度是外面这个div的宽高。同时a标签与图片之间由于基线对齐而导致下面有空隙,可以把img设置为底部对齐,就可以消除下面的空隙了。在检查a标签的时候,高度没有与图片一致,可以把a标签转为块级元素解决。
<style>
.avatar {
width: 100px;
height: 100px;
border-radius: 5px;
overflow: hidden;
&>a {
display: block; /* 让a标签转为块级元素 */
}
img {
width: 100%;
height: 100%;
vertical-align: bottom;
}
}
style>
<div class="avatar">
<a href="#">
<img src="@/assets/avtar.jpg" >
a>
div>
补充:(上面这个案例中,可以直接把img转为块级元素,那样的话,a标签会自动就成了块级元素,img标签都不用vertical-align:bottom了)
<style>
.avatar {
flex-shrink: 0;
width: 100px;
height: 100px;
border-radius: 5px;
overflow: hidden;
&>a {
}
img {
width: 100%;
height: 100%;
display: block;
}
}
style>
<div class="avatar">
<a href="#">
<img src="@/assets/avtar.jpg" >
a>
div>
处理滚动条抖动的问题:当使用margin:0 auto居中时,当内容少时,不会出现滚动条,当内容多时,就出现滚动条,这样当内容变化时,就会出现抖动的问题。解决办法可以是:不管内容多少,都特么给我出现滚动条 overflow-y: scroll; ,然后设置滚动条样式即可。
让一个元素隐藏的方法:
visibility:hidden和display:none的区别:
visibility:hidden和display:none有以下几种不同,分别是:
1、作用不同;2、使用后HTML元素有所不同;3、定义不同。
1、作用不同:
visibility:hidden将元素隐藏,但是在网页中该占的位置还是占着。
display:none将元素的显示设为无,即在网页中不占任何的位置。
2、使用后HTML元素有所不同:
visibility:hidden,使用该属性后,HTML元素(对象)仅仅是在视觉上看不见(完全透明),而它所占据的空间位置仍然存在,也即是说它仍具有高度、宽度等属性值。
display:none,使用该属性后,HTML元素(对象)的宽度、高度等各种属性值都将“丢失”
,所以不能用它来做过渡。
3、定义不同:
visibility属性指定一个元素是否是可见的。
display这个属性用于定义建立布局时元素生成的显示框类型。
margin-left、margin-right、margin-bottom、margin-top不仅可以设置正值,也可以设置为负值。可以在布局摆元素的位置的时候可以用,也可以做让边框重合到一起的效果。
margin-left:设置正值,可以让自身往右移动;设置负值,可以让自身往左移动;
margin-right:设置正值,可以让右边的元素往右移动;设置负值,可以让右边的元素往左移动;
margin-bottom:设置正值,可以让下边的元素往下移动;设置负值,可以让下边的元素往上移动
margin-top:设置正值,可以让自身往下移动;设置负值,可以让自身往上移动;
CSS 如何让auto height完美支持过渡动画?
Bootstrap 框架 栅格布局系统设计原理
讲讲我对position:sticky的发现和理解
sticky元素永远不会超出其父级的内容区:flex布局下,左右2边元素,左边比较高,由于flex布局,整体的右边高度与左边一致,整体的右边又有一个正常的文档流div1,和一个定位为sticky的元素div2,top是10px,下面又有一个div3,当页面向下滚动时,div2到了top为10px的位置,div2会变成固定定位,但是仍然会占据原来的空间,即div3它不会向上抢占div原来的空间,当继续向上滚动时,div2的底部与整体的底部重合时,整体会拖着div2向上移动,因为此时div2不能超出其父级区域的内容区域,这个时候,它的效果就不是固定定位的样子了,也就是sticky的元素,它始终都不会超出其父级区域的内容区域,并且它原来占的位置也不会被其它元素占据,就好像相对定位一样。所以说,它类似是固定定位 + 相对定位。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
* {
margin: 0;
padding: 0;
}
.box1 {
height: 300px;
background-color: pink;
}
.box2 {
height: 400px;
background-color: #bfa;
display: flex;
}
.box2-left {
flex-basis: 75%;
}
.box2-right {
flex-basis: 25%;
background-color: lightblue;
padding: 10px;
}
.box2-right .sider {
position: sticky;
top: 20px;
height: 100px;
background-color: cyan;
}
.sider-2 {
height: 100px;
background-color: palegoldenrod;
}
style>
head>
<body>
<div class="box1">div>
<div class="box2">
<div class="box2-left">div>
<div class="box2-right">
<div class="sider">div>
<div class="sider-2">div>
div>
div>
<div style="height: 1000px;">div>
body>
html>
点击某个区域,显示一个元素,点击其它地方,元素消失。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
html {
background-color: #fff;
}
body {
width: 100%;
height: 500px;
margin: 0;
background-color: #eee;
}
#outside {
width: 200px;
height: 50px;
background-color: aquamarine;
}
#modal {
background-color: #bfa;
width: 300px;
}
style>
head>
<body>
<div id="outside">
#outside 点击这里出现列表
div>
<div id="modal" style="display: none;">
<ul>
<li>1li>
<li>2li>
<li>3li>
ul>
div>
<script>
window.onload = function () {
const outside = document.getElementById("outside");
outside.addEventListener("click", viewModal);
const body = document.getElementsByTagName("body")[0];
body.addEventListener("click", hideModal);
const modal = document.getElementById("modal");
// 防止点击 modal 列表时列表消失
modal.addEventListener("click", (e) => { stopProp(e); });
}
function viewModal (e) {
stopProp(e); // 防止事件冒泡导致触发body上绑定的点击事件
const modal = document.getElementById("modal");
const disp = modal.style.display;
modal.style.display = disp === "none" ? "block" : "none";
}
function hideModal () {
const o = document.getElementById("modal");
o.style.display = "none";
}
/**
* 阻止事件冒泡
*/
function stopProp (e) {
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
}
script>
body>
html>
div中包裹一个span和一个button,让span和button分别靠到左右2边去,可以给div设置display:flex;然后button来个margin-left:auto,即可。当然,觉得最简单的方法就是justify-content:space-between;
display:flex让左边占固定大小,右边占满剩余空间的另外一种方式:
div开启flex布局后,左边设置width和min-width,然后右边设置的宽度为100%,即可。可看下面的案例。(也可以父元素使用flex布局,两边子元素设置固定大小,中间的子元素宽度设置100%,也可以让中间的元素占满剩余空间)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.box1 {
display: flex;
background-color: #ccc;
}
.div1 {
width: 50px;
min-width: 50px;
background-color: pink;
height: 50px;
word-break: break-word;
}
.span1 {
width: 100%;
background-color: #bfa;
text-align: right;
}
style>
head>
<body>
<div class="box1">
<div class="div1">11111111111111div>
<span class="span1">我是spanspan>
div>
body>
html>
span {
font-size: 16px;
/* 不要换行 */
display: inline-block;
width: max-content;
}
一个元素,正常显示,如果刚开始没有指定动画,一旦通过js加上了动画(一般通过添加类名来添加指定的动画,或者通过animation指定动画),那么元素会立刻有动画。
一个元素,添加了动画,并且正常显示,那么页面在刚开始加载的时候,就会立刻展示动画
一个元素,正常显示,并且已经添加了动画,后面通过js修改更换了animation属性(比如:通过js给元素添加了一个类名,这个类名里面指定了animation动画,这个动画覆盖了原来的动画),也会立刻按新指定的动画开始播放动画
利用2个按钮,让box1的位置左右移动( -100px~100px之间移动)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
body {
margin: 0;
}
.box1 {
width: 100px;
height: 100px;
background-color: pink;
}
@keyframes leftIn {
0% {
transform: translateX(-100px);
}
100% {
transform: translateX(100px);
}
}
.l-in {
animation: leftIn 1s;
transform: translateX(100px);
}
@keyframes leftOut {
0% {
transform: translateX(100px);
}
100% {
transform: translateX(-100px);
}
}
.l-out {
animation: leftOut 1s;
transform: translateX(-100px);
}
style>
<script>
window.onload = function() {
document.querySelector('#btn01').onclick=function() {
document.querySelector('.box1').classList.remove('l-out')
document.querySelector('.box1').classList.add('l-in')
}
document.querySelector('#btn02').onclick=function() {
document.querySelector('.box1').classList.remove('l-in')
document.querySelector('.box1').classList.add('l-out')
}
}
script>
head>
<body>
<div class="box1" >div>
<button id="btn01">btn01-inbutton>
<button id="btn02">btn02-outbutton>
body>
html>
利用两个按钮,让box1的宽度来回变化(100px~200px动画变化)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
body {
margin: 0;
}
@keyframes widen{
0% {
width: 100px;
}
100% {
width: 200px;
}
}
@keyframes widen-reverse{
0% {
width: 200px;
}
100% {
width: 100px;
}
}
.box1 {
width: 100px;
height: 100px;
background-color: pink;
}
.widen {
animation: widen 2s;
width: 200px;
}
.widen-reverse {
animation: widen-reverse 2s;
width: 100px;
}
style>
<script>
window.onload = function () {
let box1 = document.querySelector('.box1')
document.querySelector('#btn01').onclick = function () {
box1.classList.remove('widen-reverse')
box1.classList.add('widen')
}
document.querySelector('#btn02').onclick = function () {
box1.classList.remove('widen')
box1.classList.add('widen-reverse')
}
}
script>
head>
<body>
<div class="box1" id="box1">div>
<button id="btn01">btn01-inbutton>
<button id="btn02">btn02-outbutton>
body>
html>
import { useIntersectionObserver } from "@vueuse/core";
import { Directive, DirectiveBinding } from "vue";
/**
* v-animate 元素显示动画
*/
export const animate: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const { value } = binding;
const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
// 元素进入可视区
if (isIntersecting) {
stop();
const { top } = el.getBoundingClientRect();
const h = document.documentElement.clientHeight || document.body.clientHeight;
if (top < h) {
el.style.visibility = "visible";
el.style.animationName = value;
}
}
});
},
};
<div class="friends">
<div class="friend-item" v-animate="['slideUpBigIn']" v-for="friend in friendList" :key="friend.id">
<a target="_blank" :href="friend.url">
<img class="image" v-lazy="friend.avatar" />
a>
<div class="info">
<a class="name" target="_blank" :href="friend.url" :style="{ color: friend.color }">{{
friend.name
}}a>
<p class="desc">{{ friend.introduction }}p>
div>
div>
div>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.box1 {
height: 1000px;
background-color: #bfa;
}
style>
<script>
const m = (e) => { e.preventDefault() };
window.onload = ()=>{
let btn1 = document.querySelector('#btn1')
let btn2 = document.querySelector('#btn2')
btn1.onclick = ()=> {
document.body.style.overflow = 'hidden';
document.addEventListener("touchmove", m, false);
}
btn2.onclick = ()=> {
document.body.style.overflow = 'auto';
document.removeEventListener("touchmove", m, true);
}
}
script>
head>
<body>
<div class="box1">div>
<button id="btn1">btn1button>
<button id="btn2">btn2button>
body>
html>
获取当前vue对象_vue获取当前点击元素的dom对象
$event.target:触发事件的元素对象(不一定是绑定事件的对象,会因为事件冒泡变化)
$event.currentTarget:绑定事件的元素对象