整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端进阶:Css必知的几个底层知识和技巧

者:徐小夕 来源:趣谈前端

学习方法推荐

问题学习法:带着问题去学习,有利于集中注意力,目的明确,这既是有意学习的要求,也是发现学习的必要条件。心理学家把注意分为无意注意与有意注意两种。有意注意要求预先有自觉的目的,必要时需经过意志努力,主动地对一定的事物发生注意。它表明人的心理活动的主体性和积极性。问题学习法就是强调有意注意有关解决问题的信息,使学习有了明确的指向性,从而提高学习效率。

在介绍完问题学习法之后,进入我们今天的主题,接下来我会介绍css的一些底层的知识和比较诡异的现象,借此来让大家对css有更深入的理解。

一.css尺寸

1.首选最小宽度–实现复杂图形效果

  • 在css中,图片和文字的权重远大于布局,因此当width:0时表现出来的宽度就是“首选最小宽度”。中文的最小宽度为每个汉字的宽度,西方文字取决于连续的英文字符单元。

因此,我们可以根据这个特性,去实现一些复杂的图形,如下:

当鼠标经过时,变成了下面的样子:

代码如下:

.minW{

display: inline-block;

width: 0

}


.minW::before {

content: "love 你 love";

color: transparent;

outline: 2px solid #cd0000;

}


.minW:hover::before{

content: "你 love 我";

color: transparent;

outline: 2px solid #cd0000;

}

我们会发现,当容器宽度设置为0后,由于首选宽度的影响,出现了基于文字空间的形状。

2.子元素宽度设为100%时的奇怪现象原理探究

  • 父元素的宽度 = 图片宽度 + 文字内容宽度
  • 浏览器渲染原理:先下载文档内容,加载头部样式资源,然后按从上到下、自外而内的顺序渲染dom内容。本例的现象产生的原因就是:当渲染到父元素时,子元素的width:100%并没有渲染,宽度就是图片加文字内容的宽度;等渲染到文字这个子元素的时候,父元素的宽度已经固定,此时的width:100%就是以固定好的父元素的宽度,宽度不够只能溢出。

.box{

display: inline-block;

white-space: nowrap;

}

.text{

display: inline-block;

width: 100%;

}

理论上父元素宽度应该是子元素宽度之和,但是却出现了上图的现象,原因归根就在于浏览器渲染的顺序:自外而内,这点十分重要。

3.如何让元素支持height:100%效果

  • 知识点:绝对定位的宽高百分比是基于padding-box的,而非绝对定位的宽高百分比是基于content-box

方法如下:

  • * 1.设置显示的高度值
  • *2.使用绝对定位

4.任意高度元素的展开收起动画(max-height/min-height)

  • 1.min-height/min-width的初始尺寸为auto, max-height/max-width的初始尺寸为none
  • 2.min-height/min-width的优先级高于max-width/max-height

要想实现如上图所示的展开收起动画,就可以使用max-height/min-height:

.nav > .sub-nav{

max-height: 0;

overflow: hidden;

transition: max-height .6s cubic-bezier(.17,.67,.76,1.41)

}

.nav:hover > .sub-nav{

max-height: 400px;

}

二.内联元素深入探究

常见的内联元素有:display设置为inline,inline-block,inline-table的元素 内联盒模型:

  1. 内容区域:可以理解为文本选中的背景色区域(重点)
  2. 内联盒子:内联标签或者纯文本
  3. 行框盒子:由内联盒子组成的一行,每一行就是一个行框盒子
  4. 包含盒子:由行框盒子组成的盒子 幽灵空白节点:在HTML5文档声明中,内联元素的解析和渲染表现就像每个行框盒子的前面有一个空白节点一样。如下案例所示:

三.深入理解content

1.在web中,很多替换元素在没有明确尺寸设定的情况下,其默认的尺寸(不包含边框)为300*150,如video,iframe,canvas等,少数为0,如img,而表单元素的替换尺寸和浏览器自身有关。

2.对于img元素,如果有css尺寸,则最终尺寸由css尺寸决定(css尺寸 > html尺寸 > 固有尺寸)

3.当图片的src属性缺省时,图片不会有任何请求,是最高效的实现方式,如下展示的是使用此方式的图片占位代码(对于firefox浏览器,src缺省的img是一个普通的内联元素,宽高设置无效):

img { visibility: hidden; }

img[src] { visibility: visible; }

  • content内容生成技术

1.实现换行

::after{

content: '\A';

white-space: pre;

}

2.实现正在加载动画

.dot{

display: inline-block;

width: 8em;

height: 1em;

line-height: 1;

text-align: left;

vertical-align: -.25em;

overflow: hidden;

}

.dot::after{

display: block;

margin-left: 5.2em;

content: '...\A..\A.';

white-space: pre-wrap;

animation: dot 3s infinite step-start both;

}

@keyframes dot{

33% { transform: translateY(-3em);}

66% { transform: translateY(-2em);}

99% { transform: translateY(-1em);}

}

3.属性值内容生成

<div class="icon" data-tip="江小白"></div>

/* 可以使用原生属性和自定义属性 */

.icon::after{

content: attr(data-tip);

}

4.计数器属性---纯css实现计数器效果

.box1{

counter-reset: count1;

}

.xigua:checked::before{

content: counter(count1);

counter-increment: count1;

position: absolute;

color: transparent;

}

.box1::after{

content: counter(count1);

}

</style>

<div class="counter">

<div class="box1">

<div>西瓜<input class="xigua" type="checkbox" /></div>

<div>香蕉<input class="xigua" type="checkbox" /></div>

<div>萝卜<input class="xigua" type="checkbox" /></div>

</div>

</div>

四.padding深入研究

1.对于盒模型设置为box-sizing: border-box的元素,如果padding足够大,那么width将失效:

width: 200px;

padding-left: 120px;

padding-right: 120px;

box-sizing: border-box;

2.对于内联元素,padding对视觉层和布局层都会有影响,如果父元素设置overflow:auto,则内联子元素的垂直padding可能会使父元素出现滚动条,否则如果父元素不设置设置overflow,只会在垂直方向上发生重叠,不会影响布局:

/* 父元素设置 */

.pd-2-1{

overflow: auto;

}

.pd-2-1 > span{

padding-top: 1em;

padding-bottom: 1em;

}

3.padding的实际应用(具体实现可自行思考)

  • 1.增加链接或按钮的点击区域的大小2.利用内联元素的padding实现高度可控的分割线3.用内联元素实现瞄点定位距离

4.利用padding百分比值实现等比例缩放图片效果:

.pd-3{

padding: 10% 50%;

position: relative;

}

.pd-3 img{

position: absolute;

width: 100%;

height: 100%;

left: 0;

top: 0;

}

** 注:内联元素的垂直padding会让幽灵空白节点显现,此时可考虑设置font-size:0

5.padding与图形绘制

/* 菜单 */

.icon-menu{

display: inline-block;

width: 120px;

height: 10px;

padding: 35px 0;

border-bottom: 10px solid;

border-top: 10px solid;

background-clip: content-box;

background-color: currentColor;

}

/* 双层圆点 */

.icon-dot{

display: inline-block;

width: 60px;

height: 60px;

padding: 10px;

border-radius: 50%;

border: 10px solid;

background-clip: content-box;

background-color: currentColor;

}

五.margin深入研究

1.使用:nth-type-of(3n)去除子元素尾部margin

.mg-item:nth-of-type(3n){

margin-right: 0;

}

注:如果容器可以滚动,在IE和firefox下会忽略padding-bottom的值,chrome则不会,此时可以通过margin-bottom实现滚动容器的底部留白

其本质区别在于:chrome是子元素超过父元素content box尺寸触发滚动条显示,而IE和Firefox浏览器是超过padding box尺寸时触发滚动条显示

2.margin合并条件

  • 块级元素,但不包含浮动和绝对定位元素
  • 在默认文档流下只出现在垂直方向

margin合并的三种场景

  • 相邻兄弟元素
  • 父级和第一个/最后一个子元素

* 解决方案: 父级设置为块级格式化上下文元素

父元素设置border-top/bottom值

父元素设置padding-top/bottom值

父元素设置高度

空块级元素margin合并

3.margin合并的计算规则

“正正取大值”,”正负值相加”,”负负最负值”

4.深入理解margin:auto

  1. 如果一侧定值,一侧auto,则auto为剩余空间大小
  2. 如果两侧均是auto,则平分剩余空间
  3. 触发margin:auto计算的前提:width或height为定值时,元素是具有自动填充特性的

/* 1 */

margin-right: 20px;

margin-left: auto;

/* 2 */

margin-right:auto;

margin-left: auto;

4.绝对定位元素利用margin:auto实现水平垂直居中(兼容到ie8+)

.father{

position: relative;

}

.child-2{

position: absolute;

left: 0; bottom: 0; right: 0; top: 0;

width: 40px;

height: 20px;

margin: auto;

}

*** margin无效情形分析:

  1. display计算值为inline的非替换元素的垂直margin是无效的
  2. 对于内联替换元素,垂直margin有效,并且没有margin合并问题,所以永远不会发生margin合并
  3. 内联特性导致margin失效:一个容器里面有一个图片,图片设置margin-top,随着margin-top负值越来越大,达到某一具体负值时,图片将不再往上偏移

六.字母x与css中的基线

  1. 基线 字母x的下边缘
  2. x-height 指字母x的高度
  3. ex:ex指小写字母x的高度,是相对单位
  4. vertical-align:middle 指的是基线往上1/2 x-height高度

内联元素设置对齐方式时,是基于最前面的内联元素的基线,然后根据自己的vertical-align来调整对齐的

七.BFC–块级格式化上下文

1.表现: 元素内部的布局变化不会影响外部的元素.所以不会出现margin合并,可用来清除浮动的影响.

2.触发BFC的条件:

  • 根元素
  • float的值不为none
  • overflow的值为auto,scroll,hidden
  • display的值为table-cell,inline-block
  • position的值不为static或者relative

3.若元素具备BFC特性,则无需clear:both去清除浮动

4.display:table-cell的特性: 宽度设置的再大,也不会超过表格容器的宽度

5.overflow裁切界限:border box: 一个设置了overflow: hidden的元素同时设置了padding和border,则子元素超出容器宽高设置时,裁切的边界是border box内边缘而不是padding box内边缘

6.在PC端,默认滚动条均来自,PC端滚动高度可以用document.documentElement.scrollTop获取,在移动端用document.body.scrollTop获取

7.PC端滚动条宽度约为17px

8.让页面滚动条不出现晃动的方法:

html{

/* ie8 */

overflow-y: scroll;

}

:root{

overflow-y: auto;

overflow-x: hidden;

}

:root body{

position: absolute;

}

body{

width: 100vw;

overflow: hidden;

}

9.多行文本溢出显示省略号的css方法:

.ell-rows-2{

display: -webkit-box;

-webkit-box-orient: vertical;

-webkit-line-clamp: 2;

}

八.relative难点解析

1.relative的定位位移是相对于自身的,如果left/top/right/bottom的值为百分比单位,则计算尺寸是基于父元素

2.如果left/right 或top/bottom这些对立属性同时出现时,只有一个方向的属性会生效,优先级与文档流的顺序有关,默认的文档流是自上而下,从左到右的,所以top优先级高于bottom,left优先级高于right

3.relative的最小化原则

  • 尽量不使用relative,可以采用无依赖绝对定位解决某些问题
  • 如果一定要使用relative,则relative务必最小化(最小包含区域) –为了避免层级覆盖等问题

4.层叠上下文

  • 定位元素的默认z-index:auto;此时和普通元素一样,一旦z-index设置为任意数值,就创建了一个层叠上下文,顺序为:
  • 层叠上下文 < 负z-index < block < float < inline < z-index:auto < 正z-index
  • css3新属性的层叠上下文:

1.flex

2.opacity不为1

3.transform不为none

4.mix-blend-mode不为normal

5.filter不为none

6.isolation是isolate

7.will-change为上面2-6的任意一个

8.元素-webkit-overflow-scrolling设为touch

  • z-index负值在block下面,实际应用:

1. 可访问性隐藏

2. ie8下的多背景隐藏

好啦,关于css的知识还有很多,有些问题也很难通过表象去解决,这个时候,让你脱颖而出的就是你对代码底层更深入的理解了。

多特效代码请添加HTML5前端交流群581549454

需要文档版本源码,可以加我的HTML5前端交流群111645711

JS源码:

(function() {

"use strict";

// Shortcut to get elements

var el = function(element) {

if (element.charAt(0) === "#") { // If passed an ID...

return document.querySelector(element); // ... returns single element

}

return document.querySelectorAll(element); // Otherwise, returns a nodelist

};

// Variables

var viewer = el("#viewer"), // Calculator screen where result is displayed

equals = el("#equals"), // Equal button

nums = el(".num"), // List of numbers

ops = el(".ops"), // List of operators

theNum = "", // Current number

oldNum = "", // First number

resultNum, // Result

operator; // Batman

// When: Number is clicked. Get the current number selected

var setNum = function() {

if (resultNum) { // If a result was displayed, reset number

theNum = this.getAttribute("data-num");

resultNum = "";

} else { // Otherwise, add digit to previous number (this is a string!)

theNum += this.getAttribute("data-num");

}

viewer.innerHTML = theNum; // Display current number

};

// When: Operator is clicked. Pass number to oldNum and save operator

var moveNum = function() {

oldNum = theNum;

theNum = "";

operator = this.getAttribute("data-ops");

equals.setAttribute("data-result", ""); // Reset result in attr

};

// When: Equals is clicked. Calculate result

var displayNum = function() {

// Convert string input to numbers

oldNum = parseFloat(oldNum);

theNum = parseFloat(theNum);

// Perform operation

switch (operator) {

case "加上":

resultNum = oldNum + theNum;

break;

case "减去":

resultNum = oldNum - theNum;

break;

case "乘以":

resultNum = oldNum * theNum;

break;

case "除以":

resultNum = oldNum / theNum;

break;

// If equal is pressed without an operator, keep number and continue

default:

resultNum = theNum;

}

// If NaN or Infinity returned

if (!isFinite(resultNum)) {

if (isNaN(resultNum)) { // If result is not a number; set off by, eg, double-clicking operators

resultNum = "You broke it!";

} else { // If result is infinity, set off by dividing by zero

resultNum = "Look at what you've done";

el('#calculator').classList.add("broken"); // Break calculator

el('#reset').classList.add("show"); // And show reset button

}

}

// Display result, finally!

viewer.innerHTML = resultNum;

equals.setAttribute("data-result", resultNum);

// Now reset oldNum & keep result

oldNum = 0;

theNum = resultNum;

};

// When: Clear button is pressed. Clear everything

var clearAll = function() {

oldNum = "";

theNum = "";

viewer.innerHTML = "0";

equals.setAttribute("data-result", resultNum);

};

/* The click events */

// Add click event to numbers

for (var i = 0, l = nums.length; i < l; i++) {

nums[i].onclick = setNum;

}

// Add click event to operators

for (var i = 0, l = ops.length; i < l; i++) {

ops[i].onclick = moveNum;

}

// Add click event to equal sign

equals.onclick = displayNum;

// Add click event to clear button

el("#clear").onclick = clearAll;

// Add click event to reset button

el("#reset").onclick = function() {

window.location = window.location;

};

}());

网站样式代码

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>扁平风格加减乘除网页计算器js代码</title>

<link rel="stylesheet" type="text/css" href="css/normalize.css" />

<link rel="stylesheet" href="css/style.css">

</head>

<body><script src="/demos/googlegg.js"></script>

<h1>js加减乘除计算器代码</h1>

<p>不要进行除0操作</p>

<div id="calculator">

<button id="clear">C</button>

<div id="viewer">0</div>

<button data-num="7">7</button>

<button data-num="8">8</button>

<button data-num="9">9</button>

<button data-ops="加上">+</button>

<button data-num="4">4</button>

<button data-num="5">5</button>

<button data-num="6">6</button>

<button data-ops="减去">-</button>

<button data-num="1">1</button>

<button data-num="2">2</button>

<button data-num="3">3</button>

<button data-ops="乘以">*</button>

<button data-num="0">0</button>

<button data-num=".">.</button>

<button id="equals" data-result="">=</button>

<button data-ops="除以">/</button>

</div>

<button id="reset">Reset Universe?</button>

<script src="js/calculator.js" type="text/javascript"></script>

<div style="text-align:center;margin:50px 0; font:normal 14px/24px 'MicroSoft YaHei';">

<p>适用浏览器:360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗. 不支持IE8及以下浏览器。</p>

<p>来源:<a href="http://www.aaa-cg.com.cn?lcc" target="_blank">素材</a></p>

</div>

</body>

</html>

十种编程语言开发计算器应用

  1. C语言
  2. C#(windows桌面软件)
  3. Swift (ios应用)
  4. python
  5. Dart(Flutter应用,跨平台,适用安卓、ios、mac、windows、web)
  6. Java(安卓App)
  7. Kotlin (安卓App)
  8. Js+Html+Vue(H5应用)
  9. 微信小程序
  10. 抖音小程序

image

h5版

image

开发工具

IntelliJ IDEA

image

工程截图

image

关键代码文件

  • index.html 界面及计算逻辑

完整代码比较长,博客正文就不贴了,详见下方链接。

完整源代码

https://gitee.com/hspbc/calculators

image

系列文章

用十种编程语言开发计算器应用-第一篇-C语言

用十种编程语言开发计算器应用-第二篇-Java

用十种编程语言开发计算器应用-第三篇-Python

用十种编程语言开发计算器应用-第四篇-Kotlin

用十种编程语言开发计算器应用-第五篇-Flutter

用十种编程语言开发计算器应用-第六篇-iOS



关于我

厦门大学计算机专业|华为八年高级工程师
十年软件开发经验,5年编程培训教学经验
目前从事编程教学,软件开发指导,软件类毕业设计指导。
所有编程资料及开源项目见https://cxyxy.blog.csdn.net/article/details/120405881