前端开发 大前端 W3Cbest

一个专注 WEB 开发的技术博客

0%

如果有一个数组,我们只取其中的偶数或奇数该如何取值呢,下面一组数据是我们通过接口拿到的,其实我们只要奇数的一部分,1,3,5,7…等,如图:

\["1701班",11,0,"0%",0,"0%",0,"0%",1,"9.09%",7,"63.64%",2,"18.18%",0,"0%",0,"0%",0,"0%",1,"9.09%"\]

!\[](http://www.w3cbest.com/wp-content/uploads/2018/09/20180926133157.jpg) 我们只要一个if条件判断就可以了,操作如下: js

res = {"data":{
  "head":\["人数","比例"\],
  "datas":\[
  {"data":\["1701班",11,0,"0%",0,"0%",0,"0%",1,"9.09%",7,"63.64%",2,"18.18%",0,"0%",0,"0%",0,"0%",1,"9.09%"\]},
  {"data":\["班级平均",21,"0","0%","0","0%","0","0%","3","28.57%","5","47.62%","1.5","14.29%","0","0%","0","0%","0.5","4.76%","0.5","4.76%"\]},
  {"data":\["全年级",21,0,"0%",0,"0%",0,"0%",6,"28.57%",10,"47.62%",3,"14.29%",0,"0%",0,"0%",1,"4.76%",1,"4.76%"\]}
  \],
  "title":\["90以下","90 ~ 97","97 ~ 104","104 ~ 111","111 ~ 118","118 ~ 125","125 ~ 132","132 ~ 139","139 ~ 146","146以上"\]
  }
}
document.getElementById('id').innerHTML = template('tpl', res);

template

<script id="tpl" type="text/html">
  <thead>
    <tr>
      <th>班级</th>
      {{each title value i}}
      <th>{{value}}</th>
      {{/each}}
    </tr>
</thead>
<tbody>
  {{each datas item}}
  <tr>
    {{each item.data value i}}
    {{if (i % 2 == 0)}}
    <td>{{value}}</td>
    {{/if}}
    {{/each}}
  </tr>
  {{/each}}
</tbody>
</script>

其实很简单,就跟跟平时普通的if判断一样,都是取模,但是要注意在这里面要有始有终,有{{if}}就得有对应的{{/if}},有{{each}}就得有对应的{{/each}}

我已经使用CSS多年了,但直到最近我还没有深入研究过关于 CSS 选择器的主题。 为什么我需要学习 CSS 选择器呢? 我们现在知道了所有的内部选择器了吗? 问题是(至少对我来说是这样)随着时间的推移,很容易习惯在每个项目上使用相同的习惯的选择器集合来完成你要做的事情。 因此,我自己对 CSS 选择器知识进行了深入的审查,并发现了一些有趣的内容,这些内容对我来说是新的,或者是以前我从来没有想过这些使用方式。 我还发现了一些很酷的新选择器,将来可用,但还没有广泛使用。 我们一起来深入研究一下各种类型的 CSS 选择器吧。 您在日常工作中已经使用了,或者本文没涉及到的 CSS 选择器技能欢迎留言告诉我。 准备好提升你的 CSS 选择器技能了吗?我们一起 GO!

组合选择器

让我们从熟悉的选择器开始。组合选择器用于选择子元素和兄弟元素,并且相信大家已经使用了很长一段时间了吧。

  • 一般子元素选择器(空格)。例如A B。
  • 直接子元素选择器。例如 A > B 。
  • 相邻兄弟元素选择器。例如 A + B。
  • 一般兄弟元素选择器。例如 A ~ B。

您应该熟悉相邻兄弟元素选择器 A + B ,他会选择紧跟 A 的 B 元素。但是一般兄弟元素选择器 A~B 呢? 他将选择跟随 A 的所有兄弟 B 元素: 以下是实例:

See the Pen Combinator Selectors by David Gwyer (@dgwyer) on CodePen.

第二行 New York 行被选中是因为它紧跟在第一行之后 table tbody tr:first-child + tr,并且最后两个城市被高亮显示,因为他们被一般兄弟选择器 table tbody tr:nth-child(4) ~ tr 匹配,也就是第四行之后的所有行。

属性选择器

我非常喜欢属性选择器。当您需要将包含某个属性的元素与特定值匹配时,它们可以非常灵活。

See the Pen Attribute Selectors #1 by David Gwyer (@dgwyer) on CodePen.

此示例演示如何选择所有复选框元素并将样式应用于其匹配标签,以使其变为粗体和蓝色。 然后,我们覆盖具有特定名称的 chk2 复选框的样式,并将其匹配的标签着色为红色。 请注意其他表单元素标签如何不受影响且未应用标签样式。 属性选择器不仅适用于表单元素,它们还可以定位任何元素的属性。 您可以匹配任何属性,而不仅仅是官方支持的属性。 此外,您可以检查属性是否存在,如下所示:

button[icon]

这匹配包含 icon 属性的

CSS Grid 布局是 CSS 中最强大的布局系统。与 flexbox 的一维布局系统不同,CSS Grid 布局是一个二维布局系统,也就意味着它可以同时处理列和行。通过将 CSS 规则应用于 父元素 (成为 Grid Container 网格容器)和其 子元素(成为 Grid Items 网格项),你就可以轻松使用 Grid(网格) 布局。 这篇文章最初是从Chris House的指南中移植过来的,并且一直由CSS-Tricks工作人员和付费作家保持最新。 CSS网格布局(又称“网格”),是一个二维的基于网格的布局系统,旨在完全改变我们设计基于网格的用户界面的方式。CSS一直被用来布局我们的网页,但它从来没有做得很好。一开始我们用表格(table),然后是浮动(float),再是定位(postion)和内嵌块(inline-block),但是所有这些方法本质上都是一些技巧,忽略了许多重要的功能(例如,垂直居中)。Flexbox 的出现很大程度上改善了我们的布局方式,但它的目的是为了解决更简单的一维布局,而不是复杂的二维布局(Flexbox和Grid实际上配合得很好)。Grid是第一个专门为解决布局问题而创建的CSS模块,自从我们创建网站以来,我们一直在努力解决布局问题。 有两个主要因素激发了我创建本指南的灵感。第一个是 Rachel Andrew 出色的书籍 为 CSS Grid 布局做好准备。这本书对 Grid 布局做了全面,清晰的介绍 ,也是本指南的基础。我强烈建议你购买并阅读。另一个灵感来自 Chris Coyier 的 Flexbox 布局完整指南,这也是我学习 flexbox 首选的资源。这篇文章是帮助了很多人,这点从 Google “flexbox” 排名第一就可以看出来。你会发现那篇文章和我的文章有很多相似之处,为什么不跟随最好的文章呢? 本指南的目的是介绍存在于最新版本的规范中 Grid(网格) 概念。所以我不会覆盖过时的 IE 语法,而且随着规范的逐渐成熟,我会尽我最大的努力去更新这个指南。

基础知识和浏览器支持

首先,你必须使用 display: grid 将容器元素定义为一个 grid(网格) 布局,使用 grid-template-columns 和 grid-template-rows 设置 列 和 行 的尺寸大小,然后通过 grid-column 和 grid-row 将其子元素放入这个 grid(网格) 中。与 flexbox 类似,网格项(grid items)的源(HTML结构)顺序无关紧要。你的 CSS 可以以任何顺序放置它们,这使得使用 媒体查询(media queries)重新排列网格变得非常容易。定义整个页面的布局,然后完全重新排列布局以适应不同的屏幕宽度,这些都只需要几行 CSS ,想象一下就让人兴奋。Grid(网格) 布局是有史以来最强大的 CSS 模块之一。 截至2017年3月,许多浏览器都提供了对 CSS Grid 的原生支持,而且无需加浏览器前缀:Chrome(包括 Android ),Firefox,Edge,Safari(包括iOS)和 Opera 。 另一方面,Internet Explorer 10和11支持它,但是是一个过时的语法实现。 现在是时候使用 Grid 布局网页了! 这个浏览器支持数据来自Caniuse,它有更多细节。数字表示浏览器支持该版本及以上版本的功能。

复制代码

重要术语

在深入了解 Grid 的概念之前,理解术语是很重要的。由于这里涉及的术语在概念上都很相似,如果不先记住 Grid 规范定义的含义,很容易混淆它们。但是别担心,术语并不多。

网格容器(Grid Container)

应用 display: grid 的元素。这是所有 网格项(grid item)的直接父级元素。在这个例子中,container 就是 网格容器(Grid Container)。

网格项(Grid Item)

网格容器(Grid Container)的子元素(例如直接子元素)。这里 item 元素就是网格项(Grid Item),但是 sub-item 不是。

网格线(Grid Line)

构成网格结构的分界线。它们既可以是垂直的(“列网格线(column grid lines)”),也可以是水平的(“行网格线(row grid lines)”),并位于行或列的任一侧。例如,这里的黄线就是一条列网格线。

网格轨道(Grid Track)

两条相邻网格线之间的空间。你可以把它们想象成网格的列或行。下图是第二条和第三条 行网格线 之间的 网格轨道(Grid Track)。

网格单元格(Grid Cell)

两个相邻的行和两个相邻的列网格线之间的空间。这是 Grid(网格) 系统的一个“单元”。下图是第 1 至第 2 条 行网格线 和第 2 至第 3 条 列网格线 交汇构成的 网格单元格(Grid Cell)。

网格区域(Grid Area)

4条网格线包围的总空间。一个 网格区域(Grid Area) 可以由任意数量的 网格单元格(Grid Cell) 组成。下图是 行网格线1和3,以及列网格线1和3 之间的网格区域。

Grid(网格) 属性目录

网格容器(Grid Container) 属性

格项(Grid Items) 属性

display

grid-column-start

grid-template-columns

grid-column-end

grid-template-rows

grid-row-start

grid-template-areas

grid-row-end

grid-template

grid-column

grid-column-gap

grid-row

grid-row-gap

grid-area

justify-items

justify-self

justify-items

align-self

justify-items

place-self

align-items

place-items

justify-content

align-content

place-content

grid-auto-columns

grid-auto-rows

grid-auto-flow

grid

父元素 网格容器(Grid Container) 属性

 

display

将元素定义为网格容器,并为其内容建立新的 网格格式上下文。 值:

  • grid :生成一个块级网格
  • inline-grid :生成一个内联网格

.container {
display: grid inline-grid;
}

注意:通过嵌套元素(也称为子网格,即 subgrid )向下传递网格参数的能力已移至CSS Grid 规范的Level 2 版本。这里有一个快速解释

grid-template-columns/grid-template-rows

使用空格分隔的值列表,用来定义网格的列和行。这些值表示 网格轨道(Grid Track) 大小,它们之间的空格表示网格线。 值:

  • : 可以是长度值,百分比,或者等份网格容器中可用空间(使用 fr 单位)
  • :你可以选择的任意名称

.container {
grid-template-columns: …;
grid-template-rows: …;
}

例子: 当你在 网格轨道(Grid Track) 值之间留出空格时,网格线会自动分配正数和负数名称:

.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}

但是你可以明确的指定网格线(Grid Line)名称,例如 值。请注意网格线名称的括号语法:

.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

请注意,一条网格线(Grid Line)可以有多个名称。例如,这里的第二条 行网格线(row grid lines) 将有两个名字:row1-end 和 row2-start :

.container {
grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果你的定义包含多个重复值,则可以使用 repeat() 表示法来简化定义:

.container {
grid-template-columns: repeat(3, 20px [col-start]);
}

上面的代码等价于:

.container {
grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}

如果多行共享相同的名称,则可以通过其网格线名称和计数来引用它们。

.item {
grid-column-start: col-start 2;
}

fr 单元允许你用等分网格容器剩余可用空间来设置 网格轨道(Grid Track) 的大小 。例如,下面的代码会将每个网格项设置为网格容器宽度的三分之一:

.container {
grid-template-columns: 1fr 1fr 1fr;
}

剩余可用空间是除去所有非灵活网格项 之后 计算得到的。在这个例子中,可用空间总量减去 50px 后,再给 fr 单元的值 3 等分:

.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}

grid-template-areas

通过引用 grid-area 属性指定的 网格区域(Grid Area) 名称来定义网格模板。重复网格区域的名称导致内容跨越这些单元格。一个点号(.)代表一个空单元格。这个语法本身可视作网格的可视化结构。 值:

  • :由网格项的 grid-area 指定的网格区域名称
  • .(点号) :代表一个空的网格单元
  • none:不定义网格区域

.container {
grid-template-areas:
. none …”
“…”;
}

示例:

.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}

.container {
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: auto;
grid-template-areas:
“header header header header”
“main main . sidebar”
“footer footer footer footer”;
}

上面的代码将创建一个 4 列宽 3 行高的网格。整个顶行将由 header 区域组成。中间一排将由两个 main 区域,一个是空单元格,一个 sidebar 区域组成。最后一行全是 footer 区域组成。 你的声明中的每一行都需要有相同数量的单元格。 你可以使用任意数量的相邻的 点. 来声明单个空单元格。 只要这些点.之间没有空隙隔开,他们就代表一个单独的单元格。 注意你 不能 用这个语法来命名网格线,只是命名 网格区域 。当你使用这种语法时,区域两端的网格线实际上会自动命名。如果你的网格区域的名字是 foo,该区域的起始行网格线 和 起始列网格线 的名称将为 foo-start,而最后一条行网格线 和 最后一条列网格线 的名称将为 foo-end。这意味着某些网格线可能有多个名字,如上例中最左边的网格线,它将有三个名称:header-start,main-start 和 footer-start 。

grid-template

用于定义grid-template-rows ,grid-template-columns ,grid-template-areas 简写属性。 值:

  • none:将所有三个属性设置为其初始值
  • / :将 grid-template-columns 和 grid-template-rows 设置为相应地特定的值,并且设置grid-template-areas为none

.container {
grid-template: none / ;
}

这个属性也接受一个更复杂但非常方便的语法来指定三个上诉属性。这里有一个例子:

.container {
grid-template:
[row1-start] “header header header” 25px [row1-end]
[row2-start] “footer footer footer” 25px [row2-end]
/ auto 50px auto;
}

等价于:

.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
grid-template-areas:
“header header header”
“footer footer footer”;
}

由于 grid-template 不会重置 隐式 网格属性(grid-auto-columns, grid-auto-rows, 和 grid-auto-flow),这可能是你想在大多数情况下做的,建议使用 grid 属性而不是 grid-template。

grid-column-gap / grid-row-gap

指定网格线(grid lines)的大小。你可以把它想象为设置列/行之间间距的宽度。 值:

  • :长度值

.container {
grid-column-gap: ;
grid-row-gap: ;
}

示例:

.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-column-gap: 10px;
grid-row-gap: 15px;
}

只能在 列/行 之间创建间距,网格外部边缘不会有这个间距。 注意:这两个属性将删除 grid- 前缀,就是将 grid-column-gap 和 grid-row-gap重命名为 column-gap 和 row-gap。 Chrome 68+,Safari 11.2 Release 50+ 和Opera 54+ 已经支持无前缀的属性。  

grid-gap

grid-column-gap 和 grid-row-gap 的简写语法 值:

  • :长度值

.container {
grid-gap: ;
}

示例:

.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-gap: 15px 10px;
}

如果grid-row-gap没有定义,那么就会被设置为等同于 grid-column-gap 的值。例如下面的代码是等价的:

.container{
/* 设置 grid-column-gap 和 grid-row-gap */
grid-column-gap: 10px;
grid-row-gap: 10px;

/* 等价于 */
grid-gap: 10px 10px;

/* 等价于 */
grid-gap: 10px;
}

注意:这个属性将删除 grid- 前缀,就是将 grid-gap 重命名为 gap。 Chrome 68+,Safari 11.2 Release 50+ 和Opera 54+ 已经支持无前缀的属性。

justify-items

沿着 inline(行)轴线对齐网格项(grid items)(相反的属性是 align-items 沿着 block(列)轴线对齐)。此值适用于容器内的所有网格项。 值:

  • start:将网格项对齐到其单元格的左侧起始边缘(左侧对齐)
  • end:将网格项对齐到其单元格的右侧结束边缘(右侧对齐)
  • center:将网格项对齐到其单元格的水平中间位置(水平居中对齐)
  • stretch:填满单元格的宽度(默认值)

.container {
justify-items: start end center stretch;
}

示例:

.container {
justify-items: start;
}

.container{
justify-items: end;
}

.container{
justify-items: center;
}

.container{
justify-items: stretch;
}

这些行为也可以通过每个单独网格项(grid items) 的 justify-self 属性设置。

align-items

沿着 block(列)轴线对齐网格项(grid items)(相反的属性是 justify-items 沿着 inline(行)轴线对齐)。此值适用于容器内的所有网格项。 值:

  • start:将网格项对齐到其单元格的顶部起始边缘(顶部对齐)
  • end:将网格项对齐到其单元格的底部结束边缘(底部对齐)
  • center:将网格项对齐到其单元格的垂直中间位置(垂直居中对齐)
  • stretch:填满单元格的高度(默认值)

.container {
align-items: start end center stretch;
}

示例:

.container {
align-items: start;
}

.container {
align-items: end;
}

.container {
align-items: center;
}

.container {
align-items: stretch;
}

这些行为也可以通过每个单独网格项(grid items) 的 align-self 属性设置。

place-items

place-items 是设置 align-items 和 justify-items 的简写形式。 值:

  • :第一个值设置 align-items 属性,第二个值设置 justify-items 属性。如果省略第二个值,则将第一个值同时分配给这两个属性。

除 Edge 之外的所有主要浏览器都支持 place-items 简写属性。 有关更多详细信息,请参阅align-itemsjustify-items。  

justify-content

有时,你的网格合计大小可能小于其 网格容器(grid container) 大小。 如果你的所有 网格项(grid items) 都使用像 px 这样的非灵活单位设置大小,就可能出现这种情况。在这种情况下,您可以设置网格容器内的网格的对齐方式。 此属性沿着 inline(行)轴线对齐网格(相反的属性是 align-content ,沿着 block(列)轴线对齐网格)。 值:

  • start:将网格对齐到 网格容器(grid container) 的左侧起始边缘(左侧对齐)
  • end:将网格对齐到 网格容器 的右侧结束边缘(右侧对齐)
  • center:将网格对齐到 网格容器 的水平中间位置(水平居中对齐)
  • stretch:调整 网格项(grid items) 的宽度,允许该网格填充满整个 网格容器 的宽度
  • space-around:在每个网格项之间放置一个均匀的空间,左右两端放置一半的空间
  • space-between:在每个网格项之间放置一个均匀的空间,左右两端没有空间
  • space-evenly:在每个网格项目之间放置一个均匀的空间,左右两端放置一个均匀的空间

.container {
justify-content: start end center stretch space-around space-between space-evenly;
}

示例:

.container {
justify-content: start;
}

.container {
justify-content: end;
}

.container {
justify-content: center;
}

.container {
justify-content: stretch;
}

.container {
justify-content: space-around;
}

.container {
justify-content: space-between;
}

.container {
justify-content: space-evenly;
}

align-content

有时,你的网格合计大小可能小于其 网格容器(grid container) 大小。 如果你的所有 网格项(grid items) 都使用像 px 这样的非灵活单位设置大小,就可能出现这种情况。在这种情况下,您可以设置网格容器内的网格的对齐方式。 此属性沿着 block(列)轴线对齐网格(相反的属性是 justify-content ,沿着 inline(行)轴线对齐网格)。 值:

  • start:将网格对齐到 网格容器(grid container) 的顶部起始边缘(顶部对齐)
  • end:将网格对齐到 网格容器 的底部结束边缘(底部对齐)
  • center:将网格对齐到 网格容器 的垂直中间位置(垂直居中对齐)
  • stretch:调整 网格项(grid items) 的高度,允许该网格填充满整个 网格容器 的高度
  • space-around:在每个网格项之间放置一个均匀的空间,上下两端放置一半的空间
  • space-between:在每个网格项之间放置一个均匀的空间,上下两端没有空间
  • space-evenly:在每个网格项目之间放置一个均匀的空间,上下两端放置一个均匀的空间

.container {
align-content: start end center stretch space-around space-between space-evenly;
}

示例:

.container {
align-content: start;
}

.container {
align-content: end;
}

.container {
align-content: center;
}

.container {
align-content: stretch;
}

.container {
align-content: space-around;
}

.container {
align-content: space-between;
}

.container {
align-content: space-evenly;
}

place-content

place-content 是设置 align-content 和 justify-content 的简写形式。 值:

  • :第一个值设置 align-content 属性,第二个值设置 justify-content 属性。如果省略第二个值,则将第一个值同时分配给这两个属性。

除 Edge 之外的所有主要浏览器都支持 place-content 简写属性。 有关更多详细信息,请参阅align-content 和 justify-content。

grid-auto-columns / grid-auto-rows

指定任何自动生成的网格轨道(grid tracks)(又名隐式网格轨道)的大小。当网格中的网格项多于单元格时,或者当网格项位于显式网格之外时,就会创建隐式轨道。(参见显式网格和隐式网格之间的区别) 值:

  • :可以是长度值,百分比,或者等份网格容器中可用空间的分数(使用 fr 单位)

.container {
grid-auto-columns: …;
grid-auto-rows: …;
}

为了说明如何创建隐式网格轨道,请考虑一下以下的代码:

.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px
}

这将生成了一个 2×2 的网格。 但现在想象一下,你使用 grid-column 和 grid-row 来定位你的网格项,像这样:

.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}

我们告诉 .item-b 从第 5 条列网格线开始到第 6 条列网格线结束,但我们从来没有定义过 第5 或 第6 列网格线。 因为我们引用的网格线不存在,所以创建宽度为 0 的隐式网格轨道以填补空缺。我们可以使用 grid-auto-columns 和 grid-auto-rows 来指定这些隐式轨道的大小:

.container {
grid-auto-columns: 60px;
}

 

grid-auto-flow

如果你有一些没有明确放置在网格上的网格项(grid items),自动放置算法 会自动放置这些网格项。该属性控制自动布局算法如何工作。 值:

  • row:告诉自动布局算法依次填充每行,根据需要添加新行 (默认)
  • column:告诉自动布局算法依次填入每列,根据需要添加新列
  • dense:告诉自动布局算法在稍后出现较小的网格项时,尝试填充网格中较早的空缺

.container {
grid-auto-flow: row column row dense column dense
}

请注意,dense 只会更改网格项的可视顺序,并可能导致它们出现乱序,这对可访问性不利。 示例: 考虑以下 HTML :

item-a
item-b
item-c
item-d
item-e

你定义一个有 5 列和 2 行的网格,并将 grid-auto-flow 设置为 row(也就是默认值):

.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}

将网格项放在网格上时,只能为其中的两个指定位置:

.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}

因为我们把 grid-auto-flow 设成了 row ,所以我们的网格看起来会是这样。注意 我们没有进行定位的网格项(item-b,item-c,item-d)会这样排列在可用的行中: 相反地,如果我们把 grid-auto-flow 设成了 column ,那么 item-b,item-c,item-d 会沿着列向下排列:

.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: column;
}

grid

在一个声明中设置所有以下属性的简写: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 和 grid-auto-flow 。(注意:您只能在单个网格声明中指定显式或隐式网格属性)。 值:

  • none:将所有子属性设置为其初始值。
  • :与grid-template 简写的工作方式相同。
  • / [ auto-flow && dense? ] ? :将grid-template-rows 设置为指定的值。 如果 auto-flow 关键字位于斜杠的右侧,则会将 grid-auto-flow 设置为 column。 如果另外指定了 dense 关键字,则自动放置算法使用 “dense” 算法。 如果省略 grid-auto-columns ,则将其设置为 auto。
  • [ auto-flow && dense? ] ? / :将 grid-template-columns 设置为指定值。 如果 auto-flow 关键字位于斜杠的左侧,则会将grid-auto-flow 设置为 row 。 如果另外指定了 dense 关键字,则自动放置算法使用 “dense” 打包算法。 如果省略 grid-auto-rows ,则将其设置为 auto。

例子: 以下两个代码块是等效的:

.container {
grid: 100px 300px / 3fr 1fr;
}

.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}

以下两个代码块是等效的:

.container {
grid: auto-flow / 200px 1fr;
}

.container {
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
}

以下两个代码块是等效的:

.container {
grid: auto-flow dense 100px / 1fr 2fr;
}

.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}

以下两个代码块是等效的:

.container {
grid: 100px 300px / auto-flow 200px;
}

.container {
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
}

它也接受一个更复杂但相当方便的语法来一次设置所有内容。您可以指定 grid-template-areas,grid-template-rows和grid-template-columns,并所有其他的子属性都被设置为它们的初始值。这么做可以在它们网格区域内相应地指定网格线名字和网格轨道的大小。用最简单的例子来描述:

.container {
grid: [row1-start] “header header header” 1fr [row1-end]
[row2-start] “footer footer footer” 25px [row2-end]
/ auto 50px auto;
}

等价于:

.container {
grid-template-areas:
“header header header”
“footer footer footer”;
grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
}

子元素 网格项(Grid Items) 属性

注意:float,display: inline-block,display: table-cell,vertical-align 和 column-* 属性对网格项无效。

grid-column-start / grid-column-end / grid-row-start / grid-row-end

通过引用特定网格线(grid lines) 来确定 网格项(grid item) 在网格内的位置。 grid-column-start / grid-row-start 是网格项开始的网格线,grid-column-end / grid-row-end 是网格项结束的网格线。 值:

  • :可以是一个数字引用一个编号的网格线,或者一个名字来引用一个命名的网格线
  • span :该网格项将跨越所提供的网格轨道数量
  • span :该网格项将跨越到它与提供的名称位置
  • auto:表示自动放置,自动跨度,默认会扩展一个网格轨道的宽度或者高度

.item {
grid-column-start: span span auto
grid-column-end: span span auto
grid-row-start: span span auto
grid-row-end: span span auto
}

示例:

.item-a {
grid-column-start: 2;
grid-column-end: five;
grid-row-start: row1-start
grid-row-end: 3;
}

.item-b {
grid-column-start: 1;
grid-column-end: span col4-start;
grid-row-start: 2
grid-row-end: span 2
}

如果没有声明指定 grid-column-end / grid-row-end,默认情况下,该网格项将占据 1 个轨道。 项目可以相互重叠。您可以使用 z-index 来控制它们的重叠顺序。

grid-column / grid-row

分别为 grid-column-start + grid-column-end 和 grid-row-start + grid-row-end 的简写形式。 值:

  • / :每个网格项都接受所有相同的值,作为普通书写的版本,包括跨度

.item {
grid-column: / / span ;
grid-row: / / span ;
}

示例:

.item-c {
grid-column: 3 / span 2;
grid-row: third-line / 4;
}

如果没有声明分隔线结束位置,则该网格项默认占据 1 个网格轨道。

grid-area

为网格项提供一个名称,以便可以 被使用网格容器 grid-template-areas 属性创建的模板进行引用。 另外,这个属性可以用作grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写。 值:

  • :你所选的名称
  • / / / :数字或分隔线名称

.item {
grid-area: / / / ;
}

示例: 作为为网格项分配名称的一种方法:

.item-d {
grid-area: header
}

作为grid-row-start + grid-column-start + grid-row-end + grid-column-end 属性的简写形式

.item-d {
grid-area: 1 / col4-start / last-line / 6
}

justify-self

沿着 inline(行)轴线对齐网格项( 相反的属性是 align-self ,沿着 block(列)轴线对齐)。此值适用于单个网格项内的内容。 值:

  • start:将网格项对齐到其单元格的左侧起始边缘(左侧对齐)
  • end:将网格项对齐到其单元格的右侧结束边缘(右侧对齐)
  • center:将网格项对齐到其单元格的水平中间位置(水平居中对齐)
  • stretch:填满单元格的宽度(默认值)

.item {
justify-self: start end center stretch;
}

示例:

.item-a {
justify-self: start;
}

.item-a {
justify-self: end;
}

.item-a {
justify-self: center;
}

.item-a {
justify-self: stretch;
}

要为网格中的所有网格项设置 行轴线(row axis) 线上对齐方式,也可以在 网格容器 上设置 justify-items 属性。

align-self

沿着 block(列)轴线对齐网格项(grid items)( 相反的属性是 justify-self ,沿着 inline(行)轴线对齐)。此值适用于单个网格项内的内容。 值:

  • start:将网格项对齐到其单元格的顶部起始边缘(顶部对齐)
  • end:将网格项对齐到其单元格的底部结束边缘(底部对齐)
  • center:将网格项对齐到其单元格的垂直中间位置(垂直居中对齐)
  • stretch:填满单元格的高度(默认值)

.item{
align-self: start end center stretch;
}

示例:

.item-a {
align-self: start;
}

.item-a {
align-self: end;
}

.item-a {
align-self: center;
}

.item-a {
align-self: stretch;
}

要为网格中的所有网格项设置 列轴线(column axis) 上的对齐方式,也可以在 网格容器 上设置align-items属性。  

place-self

place-self 是设置 align-self 和 justify-self 的简写形式。 值:

  • auto – 布局模式的 “默认” 对齐方式。
  • :第一个值设置 align-self 属性,第二个值设置 justify-self 属性。如果省略第二个值,则将第一个值同时分配给这两个属性。

示例:

.item-a {
place-self: center;
}

.item-a {
place-self: center stretch;
}

除 Edge 之外的所有主要浏览器都支持 place-self 简写属性。

动画(Animation)

根据 CSS Grid 布局模块 Level 1 规范,有 5 个可应用动画的网格属性:

  • grid-gap, grid-row-gap,grid-column-gap 作为长度,百分比或 calc。
  • grid-template-columns,grid-template-rows 作为长度,百分比或 calc 的简单列表,只要列表中长度、百分比或calc组件的值不同即可。

浏览器支持CSS网格属性

截至今天(2018年5月7日),在测试的几个浏览器中仅实现 (grid-)gap,(grid-)row-gap,(grid-)column-gap 的动画。 浏览器支持可设置动画的网格属性:

Browser

(grid-)gap, (grid-)row-gap, (grid-)column-gap

grid-template-columns

grid-template-rows

Firefox

supported ✅ 53+

supported ✅ 66+

supported ✅ 66+

Safari 12.0

not supported ❌

not supported ❌

not supported ❌

Chrome

supported ✅ 66+

not supported ❌

not supported ❌

Chrome for Android 66+, Opera Mini 33+

supported ✅

not supported ❌

not supported ❌

Edge

supported ✅ 16+

not supported ❌

not supported ❌

See the Pen CSS Grid Layout: Animation by Manuel Matuzovic (@matuzo) on CodePen.

文章来源:https://css-tricks.com/

CSS预处理器,如Sass和Less,使得CSS代码易于组织和维护。通过提供变量、混合、循环等特性,使得CSS具有动态编写的能力,从而减少重复性工作,提高开发速度。 最近,CSS开始添加一些动态特性。CSS变量 (自定义属性)已经加入规范,并且获得了大多数浏览器的支持。但是CSS混合特性还在进行中。 在这篇文章中,我们将会向你展示怎么把CSS变量应用到开发中,从而使得样式表更加可维护和DRY (Don’t Repeat Yourself)。 让我们现在开始!

CSS变量是什么?

如果你使用过任何编程语言,你肯定熟悉变量这个概念。变量让你存储和更新程序运行需要的值。 例如,考虑下面的JavaScript片段:

let number1 = 2;
let number2 = 3;
let total = number1 + number2;
console.log(total); // 5
number1 = 4;
total = number1 + number2;
console.log(total); // 7

number1和number2是两个变量,分别存储数字2和3。 total也是一个变量,存储number1number2变量的和,在这个例子中是5。你可以动态更新这些变量的值,并且在程序的任何地方使用更新后的值。在上面的代码片段中,我把number1的值更新为4,当我使用相同的变量再次执行加法操作时,存储在total中的值就变成7,而不是5了。 变量的好处在于你可以把值存储在一个地方,然后在你需要的地方修改它。这样你就不用在程序的不同地方为不同的值添加不同的变量:所有变量更新使用同一个存储地址,比如你的变量。 CSS主要是一门声明式语言,缺乏动态性。你可能会说给CSS添加变量会与CSS本身相矛盾。如果前端开发仅仅关注语义,那么给CSS添加变量确实会与CSS本身矛盾。幸运的是,网络语言更像动态语言,它会随着周围环境和开发者的需求不断变化。CSS也不例外。 总而言之,变量已经成为CSS中令人激动的实现,你很快也会发现,学习和使用它非常直观。

使用CSS变量有什么好处?

在CSS中使用变量的好处和在编程语言中没有特别大的不同。 下面是规范对上述问题的回答:

[使用CSS变量]使大文件更易于阅读,因为看起来很随意的值有了一个提示信息的名字,并且编辑这些文件更加简单,更不易于出错。因为你只需要在自定义属性处修改一次,然后这个修改就会自动应用到使用该变量的任何地方。 W3C规范

换句话说: 通过与项目相关的方式命名变量,管理和维护代码会变得更加容易。例如,如果项目的主色调保存在--primary-color中,修改项目的主色调就会变得很容易,仅仅改变该变量的值就可以,而不用去修改遍布在代码各处、不同CSS属性中的颜色值。

CSS变量和预处理器变量的不同之处?

在给网站添加样式时,你可能已经通过预处理器,如SassLess,体验过变量的灵活性带来的好处。 预处理器可以让你设置变量,并且在函数、循环和数学操作等中使用。这是不是意味着CSS变量就没有什么用处了? 不完全是,主要是因为CSS变量和预处理器变量并不一样。 不同之处在于CSS变量是运行在浏览器中的动态CSS属性,而预处理器变量会被编译成普通的CSS代码。因此,浏览器并不知道预处理器变量的存在。 这就意味着你可以更改样式表、行内样式属性和SVG展示型属性中的CSS变量,或者使用JavaScript操作它们。这是预处理器变量做不到的。CSS变量提供了更多可能性! 但这并不是说你需要在二者之间选择其一:你可以同时使用CSS变量和预处理器变量的强大功能。

CSS变量的语法

为了简单起见,在这篇文章中我使用了CSS变量这个术语,但是官方文档给出的是级联变量的CSS自定义属性。CSS自定义属性形式如下:

--my-cool-background: #73a4f4;

在自定义属性前面添加两个短横线,然后像普通的CSS属性一样给它赋值。在上面的代码片段中,给--my-cool-background自定义属性赋了一个颜色值。 级联变量部分包括使用var()函数应用自定义属性,形式如下:

var(–my-cool-background)

自定义属性的使用范围是CSS选择器的内部,var()像一个真正的CSS属性值被使用。

:root {
–my-cool-background: #73a4f4;
}
/* CSS文件的其他部分 */
#foo {
background-color: var(–my-cool-background);
}

上面的代码片段把--my-cool-background自定义属性定义在:root伪元素内,这使得自定义属性的值全局可用(:root匹配元素内的任何元素)。然后使用var()函数把值应用到ID是foo的容器的background-color属性上,然后这个容器就会得到一个淡蓝色背景。 除此之外,还可以把淡蓝色应用到多个HTML元素的其他颜色属性上,如colorborder-color等。你需要做得仅仅是通过var(--my-cool-background)获取自定义属性的值,然后应用到相应的属性上。当然,你需要好好考虑CSS变量的命名规范,使你的变量名能更好地反映变量的内容。

p {
color: var(–my-cool-background);
}

See the Pen Basic Workings of CSS Variables by SitePoint (@SitePoint) on CodePen.

你也可以在CSS变量中使用另一个CSS变量,举例如下:

--top-color: orange;
–bottom-color: yellow;
–my-gradient: linear-gradient(var(–top-color), var(–bottom-color));

上面的代码片段创建了--my-gradient变量,它的值是使用--top-color--bottom-color变量创建的一个渐变。现在,你可以在任何地方通过仅仅改变变量的值来修改渐变,而不必到处在样式表中创建渐变实例。 下面是一个在线CodePen演示。

See the Pen Setting Value of CSS Variable with Another CSS Variable by SitePoint (@SitePoint) on CodePen.

最后,在使用CSS变量的时候,还可以添加一个或多个后备值,举例如下:

var(–main-color, #333);

在上面的代码片段中,#333是一个后备值。如果没有提供后备值,当自定义属性无效或者没有赋值的时候,会使用继承值。

CSS变量是大小写敏感的

和一般的CSS属性不一样,CSS变量是大小写敏感的。 例如,var(--foo)var(--Foo)使用的是两个不同的自定义属性,分别是--foo--Foo

CSS变量是级联的

类似一般的CSS属性,CSS变量也会继承。例如,我们定义一个值是blue的自定义属性:

:root {
–main-color: blue;
}

<html>根元素内的所有元素如果应用--main-color就会继承值blue。 如果你在另一个元素里面给自定义属性赋了一个不同的值,这个元素的所有子元素就会继承这个新值,举例如下:

:root {
–main-color: blue;
}

.alert {
–main-color: red;
}

p {
color: var(–main-color);
}

<–! HTML –>

blue paragraph.

red paragraph.

上面的标记语言中的第一个段落会继承全局--main-color的值,所以字体颜色是蓝色。 具有.alert类的div元素内部的段落元素的字体颜色是红色的,因为它继承了局部范围内的--main-color变量,这个变量的值是red。

See the Pen Simple Example of CSS Variables Inheritance by SitePoint (@SitePoint) on CodePen.

现在了解了规则,让我们开始实践吧!

在SVG中使用CSS变量

CSS变量和SVG可以很好的一起工作!你可以使用CSS变量来修改内联SVG中的样式和展示型属性。 比如,你想通过SVG图标元素的父元素来给它一个不同的颜色。你可以在父元素内设置一个局部的CSS变量,然后把它赋值成你想要的颜色,然后,父元素内的图标就能从父元素继承到合适的颜色。 下面是相关代码:

/* 图标的内联SVG symbol */



x

/* 图标的第一个实例 */


上面的标记语言使用了标签,使用它可以创建不可见的SVG图形。然后使用标签实例化了一个上述图形的可见版本。使用这种方式通过简单地引用元素的ID(#close-icon)就能创建大量的图标,然后再根据你的喜好对图标进行自定义。这比重复的写同一段代码要简便的多。如果你想复习这个技术,Massimo Cassandro在他的创造你自己的SVG图标中提供了一个快速教程。 注意SVG中的圆形元素的stroke属性值和文本元素的fill属性值:它们都使用了一个CSS变量,--icon-color,这个变量定义在CSS文档的:root选择器上,如下所示:

:root {
–icon-color: black;
}

图标现在的样子如下: 如果你现在把SVG图标放到不同的容器中,然后在每个父元素的选择器中给这个变量赋不同的颜色值,你就能在不添加任何样式规则的情况下创建不同颜色的图标。真酷! 举个例子,把上面图标的一个实例放在一个有类.success的div中。

现在,在.success选择器内给–icon-color变量赋值green,然后看下效果。

.success {
–icon-color: green;
}

现在,图标的颜色变成了绿色: 查看下面完整的演示示例:

See the Pen Basic Use of SVG Icon and CSS Variables by SitePoint (@SitePoint) on CodePen.

在@keyframes动画中使用CSS变量

CSS变量可以和CSS动画一起使用,不论是在一般的HTML元素还是内联SVG元素上。只需要记住在想添加动画的元素的选择器上定义自定义属性,然后使用var()函数在@keyframes中引用。 比如,给SVG的一个有类.bubble的元素添加动画,CSS代码如下:

.bubble {
–direction-y: 30px;
–transparency: 0;
animation: bubbling 3s forwards infinite;
}

@keyframes bubbling {
0% {
transform: translatey(var(–direction-y));
opacity: var(–transparency);
}
40% {
opacity: calc(var(–transparency) + 0.2);
}
70% {
opacity: calc(var(–transparency) + 0.1);
}
100% {
opacity: var(–transparency);
}
}

你可能已经注意到我们可以使用CSS的calc()通过var()函数对变量进行计算,这使代码更加灵活。 这个例子中使用CSS变量的灵活之处是通过简单的改变相应选择器内部的变量值,就可以改变动画效果,而不必查找@keyframes指令中的每个属性。 下面是完整的CodePen演示:

See the Pen Simple Animation with CSS Variables and SVG by SitePoint (@SitePoint) on CodePen.

使用JavaScript操作CSS变量

一件更酷的事情是你可以直接通过JavaScript代码访问CSS变量。 假设有一个叫--left-pos的CSS变量,它的值的100px,定义在CSS文档的.sidebar类中:

.sidebar {
  –left-pos: 100px;
}

使用类似下面的JavaScript代码获取--left-pos的值:

// 获取你想添加动画的元素
const sidebarElement = document.querySelector(‘.sidebar’);

// 把侧边栏元素的样式存储在cssStyles变量中
const cssStyles = getComputedStyle(sidebarElement);

// 获取CSS变量–left-pos的值
const cssVal = String(cssStyles.getPropertyValue(‘–left-pos’)).trim();

// 在控制台打印CSS变量的值
// 控制台会输出变量的值为100px
console.log(cssVal);

使用类似下面的JavaScript代码给CSS变量赋值:

sidebarElement.style.setProperty(‘–left-pos’, ‘200px’);

上面的代码片段把侧边栏元素的--left-pos变量设置成200px。 相对于改变大量的类或者重写全部的CSS规则,使用CSS变量给网站添加交互更直接,也更易于维护。 查看下面的CodePen演示,你可以通过侧边栏来改变混合模式属性和背景颜色,而这仅仅需要CSS变量和JavaScript:

See the Pen Blend Modes, CSS Variables and JavaScript by SitePoint (@SitePoint) on CodePen.

浏览器对CSS变量的支持情况

除了IE11(不支持)和Microsoft Edge(buggy支持),在本文编写的时候,所有主流浏览器都完全支持CSS变量。 适配有问题的浏览器的方式之一是使用@supports进行条件查询:

section {
color: gray;
}

@supports(–css: variables) {
section {
–my-color: blue;
color: var(–my-color, ‘blue’);
}
}

因为IE/Edge支持@supports,所以上面的代码会生效。如果在var()函数中添加一个后备值,你的代码将会更加健壮,在支持的更加不好的浏览器中也能优雅降级。 所以,在Chrome和其他支持CSS变量的浏览器中, 元素内部的文本是蓝色的: IE11不支持CSS变量,文本会被渲染成灰色: 查看在线演示:

See the Pen @supports with CSS Variables by SitePoint (@SitePoint) on CodePen.

这种方式的缺点是如果你在项目中使用了大量的CSS变量,但是该项目主要通过不支持CSS变量的浏览器打开,那么代码不仅会变得有点儿复杂,维护也将会是噩梦。 在这种情况下,你可以选择使用支持cssnext的PostCSS,然后你就可以编写尖端的CSS代码了,兼容不支持的浏览器交给PostCSS去做就可以了,这有点儿像JavaScript的编译器。如果你想了解PostCSS,SitePoint Premium为其所有成员提供了有关此主题的精彩视频课程

资源

想了解更多CSS变量的细节,包括浏览器兼容问题的解决方案和有趣的例子,查看下面的资源:

有趣的例子

你还在等什么?尝试使用CSS变量并通过评论让我知道你的想法! 文章来源:https://www.sitepoint.com/

多数编程语言都支持变量。但是CSS从最初就一直缺少对原生变量的功能支持。 你写CSS吧?那你就没办法用变量。不过,你还可以用Sass这样的预编译器。 Sass这样的预编译器就把变量作为一个巨大的卖点,一个尝试新东西的原因。你知道吗?我们还真的很吃这一套。 不过互联网还在飞速前行。所以我也很开心的宣布CSS现在终于支持变量了。 预编译器支持更多的特性,其中CSS变量就是一个不错的卖点。这些工作让互联网更加接近未来。 在这篇指南里,我会展示如何使用CSS原生变量,以及如何在日常工作里使用它们,让生活变的更美好。

你会学到这些

首先,我会介绍一些CSS变量的基础知识。我相信理解CSS变量应该从这里开始。 学习基础知识是非常酷的一件事。更酷的把这些基础知识应用到现实应用当中去。 所以我会用三个例子来展示如何方便的使用CSS变量。下面我们简单过一下这三个例子。

例1:使用CSS变量创建可变组件

今天你可能已经在构建自己可变组件了。无论你是在使用React,Angular,或者Vue,CSS变量都能使这个过程简洁许多。 参见 Codepen的这个例子;

例2: 带有CSS变量的主题样式

你可能已经在别处看到过这样的用法。我接下来要展示的是CSS变量如何使得创建站点级别的主题样式更加简便。 参见 Codepen的这个例子

例3: 创建CSS变量盒

恩,这是最后一个例子。请忽略这个名字,我想不到更好的了… 注意这些盒子的颜色是动态更新的,盒子容器也是可以3D旋转的。 这个例子让我们看到如何使用JavaScript更新CSS变量,并展示出一个很好的交互效果。

接下来的更有趣!

花点时间尝试一下 Codepen上的这个例子。 请注意:本文假设你已经熟练掌握了CSS。如果你还不了解CSS,或者想学习创造让人瞠目结舌的UI,我建议你上一下我的这堂高级CSS课程(付费课程,包括85节课)。本文是其中一课的摘录(不害臊脸)。

为何变量如此重要

如果你刚开始学预编译器的变量,或者熟悉原生CSS,下面便是一些你要了解变量的原因:

原因1:提高代码可读性

无需赘言,变量让代码可读性更强,可维护性更好。

原因2: 使大型文档中的代码改动更容易

如果你所有的常量都存在一个单独的文件里,你就不需要在几千行代码里一一修改变量了。这就很容易了。 只要改一行,就结了!

原因3: 更快的发现拼写错误

在多行代码里找错,是很痛苦的一件事。更烦人的是,这个错误可能只是简单的拼写错误。很难查找。合理使用变量,就能消除一些烦心事。 因此,可读性和可维护性可以双赢。 感谢CSS变量,现在我们终于可以在原生CSS中使用它们了。

定义CSS变量

让我们从你熟悉的开始吧:JavaScript中的变量。 一个JavaScript中的变量可能是这样定义的:

var amAwesome;

然后这样赋值:

amAwesome = “awesome string”

CSS中,一个CSS变量是任意一个以两个破折号开头的”属性“值,

/*能找到这里定义变量么? */
.block {
color: #8cacea;
–color: blue
}

CSS变量作用域

还有一点你需要注意。 在JavaScript里,变量都有一个作用域。它们或是一个全局变量,或是一个局部变量。 CSS变量也一样。请看下面的例子:

:root {
–main-color: red
}

:root选择器能让我们选择DOM树里的最顶级的元素,也就是文档树。所以,这样定义的变量,也就相当于全局变量了。理解了么?

例1

假设你想设置一个存储网站主题样式的CSS变量,你会怎么做?

1,你需要使用范围选择器。用:root来定义一个全局变量。

:root {}

2,定义变量

:root {
–primary-color: red
}

请记住,CSS变量是任意一个以两个破折号开始的“属性”。就这么简单。

使用CSS变量

变量定义且被赋值后,你就可以使用它了。不过要上手还是有一些麻烦的地方。 如果你习惯了预编译器,那么肯定知道如何使用变量了。例如:

$font-size: 20px
.test {
font-size: $font-size
}

CSS变量和这稍有不同。 你需要使用var()这个函数引用变量。 上面的例子中,CSS变量是这样引用的:

:root {
–font-size: 20px
}
.test {
font-size: var(–font-size)
}

非常不同。 一旦你习惯了这样的方式,你就会爱上CSS变量的,非常爱! 另一个重要的提示是,不像Sass或者其他预编译器中的变量,你可以在很多地方使用变量。CSS的变量需要小心谨慎,如果需要你还能做数学运算。多数情况下你应该把它们当作属性值来使用。

/*下面这样是不对的*/
.margin {
–side: margin-top;
var(–side): 20px;
}

你也无法直接使用数学运算功能。运算功能需要使用calc()函数。后面遇到时我会加以讨论。

/*下面这样也不对 */
.margin {
–space: 20px * 2;
font-size: var(–space); //这不是 40px
}

如果你一定需要用数学计算,那么请使用 calc()函数,如下:

.margin {
–space: calc(20px * 2);
font-size: var(–space); /*equals 40px*/
}

值得一提的属性

有一些行为是值得提醒注意的。

1. 自定义属性是普通属性值,因此它们可以定义在任意元素上。

在段落p元素,section,aside元素或者root根元素,甚至是伪元素上使用变量,都是可以的。

2. CSS变量和普通CSS继承和叠加的规则相同

看这个例子:

div {
–color: red;
}
div.test {
color: var(–color)
}
div.ew {
color: var(–color)
}

和普通变量相同,--color的值也会从其他的div元素继承下来。

3. CSS变量也可以和@media或其他条件选择的规则同时使用

和其他属性一样,你也可以使用@media或其他的条件规则里使用变量, 例如,下面的代码改变了变量的值,在不同的设备上使用不同值。

:root {
–gutter: 10px
}
@media screen and (min-width: 768px) {
–gutter: 30px
}

4. CSS变量可以在HTML的style属性中使用

你也可以在内联样式里使用变量,它们也正常工作。

body { color: var(--color) }

CSS变量大小写敏感。请注意这一点。我为了省事全部都用小写。你的情况可能不一样。

/*这是两个不同的变量*/
:root {
–color: blue;
–COLOR: red;
}

解决多重定义

和其他属性是一样的,重定义变量也遵循标准级联规则。 下面来看个例子:

/*变量定义*/
:root { –color: blue; }
div { –color: green; }
#alert { –color: red; }

/*使用变量 */
* { color: var(–color); }

有了上面的定义,不同元素的值是什么样的呢?

我的颜色是?

我的呢?
我的颜色是?

颜色?

你能猜出来么? 第一个p元素是 blue,没有任何–color 变量定义是在 p元素的,因此它会继承自根元素 :root。

:root { –color: blue; }

第一个div是绿色green。毋庸赘述。在div`上有一个颜色变量定义。

div { –color: green; }

使用ID值为alert 定义的 div,不是绿色,而是红色red。

#alert { –color: red; }

The ID has a direct variable scoping. As such, the value within the definition will override the others. The selector #alert is more specific. 这个ID有一个更直接的变量范围。因此,这个范围内定义的变量值会覆盖其他的变量值。#alert ID选择器更具体。 最后, 在ID#alert中的这个p 是红色red。 在第一个p 元素上,并没有变量声明。可以推测,这个元素是在根元素 :root以内的,因此它的颜色是蓝色。

:root { –color: blue; }

和其他属性一样,CSS变量也是可继承的。这个值也会从其父节点上获得。

#alert { –color: red; }

解决循环依赖

循环依赖通常会在下面几种情况下发生: 变量需要依赖其自身值。也就是说,定义时就使用了var()引用其值。

:root {
–m: var(–m)
}
body {
margin: var(–m)
}

多个变量相互引用时。

:root {
–one: calc(var(–two) + 10px);
–two: calc(var(–one) - 10px);
}

请注意,不要在代码中创建这样的循环引用。

使用无效变量会怎样?

语法错误会被忽略,但是无效的使用var()会导致错误的初始值或者是继承到有问题的值。 看下面的代码:

:root {–color: 20px;}
p {background-color: red;}
p {background-color: var(–color);}

--color会被代入var(),但是这条属性值,background-color: 20px 在变量代入后是无效的(译者注:错误的颜色值)。因为backgroud-color不是继承属性,那么它的值就会是这个属性的初始值 transparent 请注意,如果你直接写backgroud-color: 20px,那么这个属性声明就是无效的。这一行之前的定义就正常工作了。

创建单一标记时,请注意

当你设置一个类似下面的属性的变量时,20px就被编译成一个单一标记。

font-size: 20px

简单理解就是,20px 就是一个单独的整体。 使用CSS变量构建独立单一标记需要十分小心。 例如,看下面的代码:

:root {
–size: 20
}

div {
font-size: var(–size)px **/*错了*/**
}

你也许会认为,font-size的值是20px,但你错了。浏览器会解析成 20 px, 注意20和px之间的空格。 因此,如果你一定需要创建独立标记,那么就一定要用变量表示这个整体。例如: --size: 20px,或者是用 calc() 这个函数,例如, calc(var(--size) * 1px),然后其中的--size 值就是20。 不要着急。如果你还不太能理解这一点,后面的例子中我会解释的更具体。

一起来动手吧!

下面就是本文里我们最期待的一部分。 我会带着大家做一些有用的例子,把实际应用中的概念都过一遍。我们开始吧。

例1: 使用CSS变量创建可变组件

假设你需要创建两个不同的按钮。基本样式相同,只有一点小小的区别。 在这个例子里,不同的属性只有 background-colorborder-color 。 那怎样处理这种情况呢?下面是一种典型的解决方案: 创建一个基类,比如 .btn,然后加上其他的不同类,例如:


.btn 包含了按钮的基本样式,例如:

.btn {
padding: 2rem 4rem;
border: 2px solid black;
background: transparent;
font-size: 0.6em;
border-radius: 2px;
}

/*on hover */
.btn:hover {
cursor: pointer;
background: black;
color: white;
}

那按钮样式如何变化呢?像这样:

/* variations */
.btn.red {
border-color: red
}

.btn.red:hover {
background: red
}

你看,这里就有重复的代码了吧?这样也好,但使用CSS变量可以更简洁。

第一步是什么呢?

把变化的颜色值用CSS变量定义出来,不要忘记加默认值!

.btn {
padding: 2rem 4rem;
border: 2px solid var(–color, black);
background: transparent;
font-size: 0.6em;
border-radius: 2px;
}

/*on hover*/
.btn:hover {
cursor: pointer;
background: var(–color, black);
color: white;
}

你这样设置background: **var(--color, black)**时,也就是说把背景设置为变量–color的值。如果这个变量不存在,那就用默认值黑色**black**替代 。 这就是设置默认值的方法,和JavaScript或者其他语言一样。 下面是有趣的部分了。 有了变量,你就可以像下面这样设置新的变量值了:

.btn.red {
–color: red
}

这就可以了。如果元素class中使用了.red,那么浏览器就能注意到不同的--color值,这样就使得不同的按钮有不同的颜色了。 这样你就可以省下来很多时间,创建可复用的组件了。 下图是简单的对比: 哦,对了,如果你有更多的变量,那还能省下很多打字的时间:

例2:使用CSS变量制作网站主题

我想你肯定遇到过这样的情况。有主题的网站可以让用户有自己定制的感觉,就像是由他们来控制一样。 下面这个例子就是我们要做的。   那么CSS变量是如何让这件事变得简单一点的呢? 让我们一起来看。 在这之前,我想提醒你,这个例子非常重要。在这个例子里,我会介绍如何使用JavaScript更新CSS变量。超有趣!你肯定会喜欢的。

我们实际要做的

CSS变量的美妙是它们的互动性。一旦它们的值发生了变化,对应CSS的属性也会相应的进行更新。 下图从概念上解释了在本例中这个过程是如何发生的 。 所以,我们需要增加一些JavaScript来监听点击事件。 在这个例子里,背景颜色和文字颜色是基于CSS变量的。 当你点击上面任何一个按钮时,它们就将对应的CSS变量设置成另一种颜色。于是,页面的背景颜色也更新了。 你看,这就是所有的内容了。 哦,还有一件事。 当我说把CSS变量设置成另一个值的时候,这又是怎样做到的呢? 即便是设置在inline style中,CSS变量也会生效。和JavaScript一起,我们就可以控制整个root文档,这样也就能设置CSS变量的值了。 理解了么? 不过前面都是说的,下面我们来看代码。

初始代码

最初代码像这样:

. . .
这段代码由三个button和一个 class是.theme 父元素组成。为了简洁一点我去掉了中间的内容部分,只用article元素替代。article元素内就是页面内容。

页面样式

这个小项目的成功点就是页面的样式。技巧其实很简单。 没必要为每种风格设置background-colorcolor,我们只需要使用变量来设置即可。 就像下面这样:

body {
background-color: **var(–bg, white)**;
color: **var(–bg-text, black)**
}

这样做目的很明显。点击每个button时,这个页面的背景和文字颜色就可以随之变化。 基于这个改变,整体的页面就很容易改变了。小菜一碟。 接下来我们就来增加处理更新值的JavaScript脚本部分。

涉及JavaScript的部分

接下来我会把项目需要的JavaScript逐步分析。

const root = document.documentElement
const themeBtns = document.querySelectorAll(‘.theme > button’)
themeBtns.forEach((btn) => {
btn.addEventListener(‘click’, handleThemeUpdate)
})

function handleThemeUpdate(e) {
switch(e.target.value) {
case ‘dark’:
root.style.setProperty(‘–bg’, ‘black’)
root.style.setProperty(‘–bg-text’, ‘white’)
break
case ‘calm’:
root.style.setProperty(‘–bg’, ‘#B3E5FC’)
root.style.setProperty(‘–bg-text’, ‘#37474F’)
break
case ‘light’:
root.style.setProperty(‘–bg’, ‘white’)
root.style.setProperty(‘–bg-text’, ‘black’)
break
}
}

别被吓到了。代码其实比你想的简单的多。 首先,创建一个对root元素的引用, const root = document.documentElement。 这里的root元素就是 HTML。一会你就明白为什么这一点很重要了。如果你很好奇,就先理解这是为了设置CSS变量使用的。 然后,对不同button也保存对应的引用, const themeBtns = document.querySelectorAll('.theme > button')querySelectorAll会返回一个可以遍历的数组结构。这样我们就可以遍历每个按钮给它们增加对应的点击事件。 就像这样:

themeBtns.forEach((btn) => {
btn.addEventListener(‘click’, handleThemeUpdate)
})

handleThemeUpdate 在哪呢?接下来就是。 点击按钮时,对应的handleThemeUpdate就会触发。因此要记下哪个按钮点击了,应该执行对应什么样的操作。 因此,这里用了一个switchoperator,不同的按钮的点击事件在这里有了区别。 现在你再回去看一下前面的JavaScript的代码。你应该能更好的理解它了。

例3: 创建CSS变量盒

假如你忘了,那再提一下,我们要做的例子是这样的: 请记住,盒子的颜色是动态变化的,盒子可以根据用户的输入进行3D的旋转。 你可以在Codepen上玩一下。 这是使用CSS变量和JavaScript共同创造出的一个即有交互性又很美妙的例子。 我们一起看看怎么做的。

代码片段

我们需要下面一些元素:

  1. 一个范围输入
  2. 一个容器来显示说明部分
  3. 一个部分用来列出不同的盒子和每一种输入

代码部分很简单,下面就是:

<section class="color-boxes">
  <div class="color-box" id="1"><input value="red"/></div>
  <div class="color-box" id="2"><input/></div>
  <div class="color-box" id="3"><input/></div>
  <div class="color-box" id="4"><input/></div>
  <div class="color-box" id="5"><input/></div>
  <div class="color-box" id="6"><input/></div>
</section>

<footer class="instructions">
    Move the slider<br/>
    Write any color in the red boxes 
</footer>

需要注意以下几点:

  1. 输入的范围是从-5050,步长是5。而且,最小值是-50
  2. 如果你不太清楚这个范围输入是什么原理,可以在 w3schools找到相关说明。
  3. 注意外层带有.color-boxes类的容器,它包含了.color-box的容器,再其中就是各种输入了。
  4. 或许应该提一下,第一个输入框的默认值是红色。

理解了页面的结构,接下来我们看一下页面样式:

  1. 首先把.slider.instructions的元素移出文档流,进行绝对定位。
  2. 然后给body元素添加日出的背景颜色,再用一朵花的背景图做装饰,放在页面的左下角。
  3. 然后把color-boxes居中对齐。
  4. 接下来给color-boxes增加样式。

我们一起来深入一下细节。下面的代码完成的是第一个任务。

/* Slider */
.slider,
.instructions {
position: absolute;
background: rgba(0,0,0,0.4);
padding: 1rem 2rem;
border-radius: 5px
}
.slider {
right: 10px;
top: 10px;
}
.slider > * {
display: block;
}

/* Instructions */
.instructions {
text-align: center;
bottom: 0;
background: initial;
color: black;
}

这段代码非常简单。我想你肯定能读懂,如果不懂就发评论或者发推。 给 body元素加上样式就复杂一些了。希望你能很好的理解这部分CSS。 因为我们需要设置元素的背景颜色和背景图像,那么我们最好使用简化的background属性来增加多种不同的背景。代码如下:

body {
margin: 0;
color: rgba(255,255,255,0.9);
background: url(‘http://bit.ly/2FiPrRA') 0 100%/340px no-repeat, var(–primary-color);
font-family: ‘Shadows Into Light Two’, cursive;
}

url部分设置向日葵图片的链接。 接下来0``100%代表图像在背景中的位置。 这里有对于CSS中background属性定位的具体阐释:

来源:the advanced guide to CSS

来源:the advanced guide to CSS

在斜线后的另一部分是代表background-size,这个值是340px。如果这个值小一些,那图片也会更小一点。 你也许会想no-repeat是什么意思,它意味着背景不允许重复。 最后,逗号之后的部分就是第二种背景声明。这次我们把background-color设置成var(primary-color)。 哦,它是一个变量。 这就意味着你需要定义这个变量,就像这样:

:root {
–primary-color: rgba(241,196,15 ,1)
}

现在的颜色是日出的黄色。不是什么大问题。接下来我们会设置更多的变量。 然后,把color-boxes居中对齐。

main.booth {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}

主要容器是布局设置成flex,然后直接将子元素放在页面中间, 也就是接下来color-box的部分。 下面我们把容器和子元素美化一下。 首先是子元素:

.color-box {
padding: 1rem 3.5rem;
margin-bottom: 0.5rem;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 0.3rem;
box-shadow: 10px 10px 30px rgba(0,0,0,0.4);
}

这样就够了。还加了一个漂亮的阴影。这样就有了酷炫的效果了。 不过这还不够。还有container-boxes容器的样式:

/* Color Boxes */
.color-boxes {
background: var(–secondary-color);
box-shadow: 10px 10px 30px rgba(0,0,0,0.4);
border-radius: 0.3rem;
transform: perspective(500px) rotateY( calc(var(–slider) * 1deg));
transition: transform 0.3s
}

棒! 这样就好多了。 让我们细化一下。 下面是简单的部分:

.color-boxes {
background: **var(–secondary-color)**;
box-shadow: 10px 10px 30px rgba(0,0,0,0.4);
border-radius: 0.3rem;
}

你知道意思,对吧? 这里用了一个新的变量。因此我们需要在root选择器里加上定义。

:root {
–primary-color: rgba(241,196,15 ,1);
–secondary-color: red;
}

这里的secondary-color是红色。这样就使得容器有一个红色的背景。 但你可能对下面的部分感到疑惑,

/* Color Boxes */
.color-boxes {
transform: perspective(500px) rotateY( calc(var(–slider) * 1deg));
transition: transform 0.3s
}

我们可以暂时简化上面代码里transfrom的属性。 例如:

transform: perspective(500px) rotateY( 30deg);

transform合并了两个不同的函数。一个是透视,一个是以Y轴为标准的旋转。 不过,perspectiverotateY又起了什么样的作用呢? perspective()函数可以使元素在3D的空间内变形。它会激活一个三维空间,使元素增加一个z轴。 你可以在 codrops看到更多关于perspective函数的介绍。 那么rotateY函数又有什么用呢? 激活了三维空间后,元素就有了x,y,z三个轴。 rotateY函数就意味着把元素以 Y 轴为中心进行旋转。 codrops的这幅图可以帮我们直观的理解这一点。

Codrops

希望这能帮你拨开云雾见天日。 回到前面的主题。 移动滑块的时候,你知道是哪个函数影响了.container-box的旋转效果么? 是的,就是这个 rotateY函数被调用了。因此这个盒元素就沿着Y轴进行旋转。 因为这个值可以通过JavaScript传给函数,所以这个值就用一个变量来表示。 那为什么要用这个变量乘以1deg呢? 按通常的经验来说,也为了自由定义变量,我们建议在创建变量时,不带单位。 这样你就可以在任何需要使用单位的时候通过calc函数达成目标。 这就使得你可以在需要时任意使用了。它即可以转化成deg, 也可以转化成一个相对于用户视窗单位vw的比例 ,你可以想怎么做就怎么做。 在这个例子中,我们把一个数字通过乘以一个1deg的值,得到了一个有单位的数值。 因为CSS并不理解数学计算,因此你需要把这个算术放在calc函数里才能得到CSS属性需要的对应数值。 这些都完成,我们就可以开始下一步了。现在我们要用JavaScript来更新这个变量值。 不过还剩下一点CSS的代码。这就是了:

/* Handle colors for each color box */
.color-box:nth-child(1) {
background: var(–bg-1)
}
.color-box:nth-child(2) {
background: var(–bg-2)
}
.color-box:nth-child(3) {
background: var(–bg-3)
}
.color-box:nth-child(4) {
background: var(–bg-4)
}
.color-box:nth-child(5) {
background: var(–bg-5)
}
.color-box:nth-child(6) {
background: var(–bg-6)
}

这又是什么鬼? 首先,nth-child选择器用来选择不同的子元素。 这里我们需要看深入一点。我们已经了解需要更新每个盒子的颜色,也知道每盒子的颜色需要用一个变量以便使用JavaScript更新,对把? 因此,我们就这样设置:

.color-box:nth-child(1) {
background: var(–bg-1)
}

简单吧? 不过还有一个问题,如果这个变量不存在,那会怎么样呢? 我们需要默认值。 这样就没问题了:

.color-box:nth-child(1) {
background: var(–bg-1, red)
}

不过在这个实际的例子里,我选择不提供任何默认值。 如果这个变量的属性值不合法,那么这个属性值就会用其初始值。 也就是说,如果 --bg-1不合法或者无效,那么背景就是它的初始值,也就是透明色。 没有明确指定时,初始值就是这个属性的默认值。例如,如果你不设置元素的background-color,那它就是默认就是透明的。 初始值也是一种默认值。 开始写JavaScript 需要写的JavaScript的部分非常少。 首先让我们处理滑块。 五行就够了!

const root = document.documentElement
const range = document.querySelector(‘.booth-slider’)

//as slider range’s value changes, do something
range.addEventListener(‘input’, handleSlider)

function handleSlider (e) {
let value = e.target.value
root.style.setProperty(‘–slider’, value)
}

很简单吧? 不过我还是要解释一下,以防我把你搞糊涂了。 首先,保存一个对slider元素的引用,const range = document.querySelector('.booth-slider') 然后给它增加一个事件,用来处理滑块值变化,range.addEventListener('input', handleSlider)。 接下来就是这个回调事件handleSlider:

function handleSlider (e) {
let value = e.target.value
root.style.setProperty(‘–slider’, value)
}

root.style.setProperty('--slider', value) 是指把root元素的style属性设置成对应值。 处理颜色变化 这和处理滑块值的变化一样简单。下面就是:

const inputs = document.querySelectorAll(‘.color-box > input’)
//as the value in the input changes, do something.
inputs.forEach(input => {
input.addEventListener(‘input’, handleInputChange)
})

function handleInputChange (e) {
let value = e.target.value
let inputId = e.target.parentNode.id
let inputBg = `–bg-${inputId}`
root.style.setProperty(inputBg, value)
}

保存一个对所有输入框的引用, const inputs = document.querySelectorAll(‘.color-box > input’)。 为每一个输入框增加一个事件处理:

inputs.forEach(input => {
input.addEventListener(‘input’, handleInputChange)
})

接下来是 handleInputChange 函数:

function handleInputChange (e) {
let value = e.target.value
let inputId = e.target.parentNode.id
let inputBg = `–bg-${inputId}`
root.style.setProperty(inputBg, value)
}

嗯… 这就没了! 样例做完了! 我怎么能忘记这些呢? 我写完这篇文章还改了初稿之后,才想起来我还没提到浏览器的兼容性。所以,让我补上这一部分。 CSS变量的浏览器支持并不差。可以说相当好了,几乎所有的现代浏览器都能支持(我写这篇文章的时候超过87%)。

caniuse

所以,你可以在生产环境中使用么?我当然说是啦!不过你还是要检查一下适用的比例。 往好的方向面看,你也可以使用 Myth类似的预编译器。它可以把你现在使用的CSS变成未来可期的CSS,超酷的,对吧? 如果你有用过postCSS的经验,那这也是一个现在使用未来CSS的不错的方法。这里有一些使用postCSS的例子。 好啦,我都讲完了。 原文翻译:https://medium.freecodecamp.org

JavaScript 模板引擎作为数据与界面分离工作中最重要一环,越来越受开发者关注,模板引擎种类也是五花八门,我就说几个安全性高、错误处理调试优,执行速度快的有artTemplate(腾讯 14k)、juicer(国外 12k)这俩个,doT除了错误处理调试差以外其他的都和这两个一样,他有一个优点是小(4k),扯远啦。 art-template 是一个简约、超快的模板引擎。 它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器。在线速度测试。 我们就讲一下讲简洁语法的渲染方式,template(filename, content)根据模板名渲染模板。前提是你已经对artTemplate有所了解, 今天我们就讲一下数组渲染的方法 数组渲染有数组对象和纯数组两种形式,我们先说数组对象,如后端返回我们接口,收到的就是一个数组。比如:

const res = [
  {"name":"小明", "age":16, "marry":"单身"},
  {"name":"小花","age":15, "marry":"有男朋友"},
  {"name":"小胖","age":15, "marry":"有女朋友"},
  {"name":"小丽","age":15, "marry":"单身"}
];

用artTemplate有个好处就是除了你的数据需要重组,其他的完全可以拿来直接用。如下 html

<div id="person"></div>

js

<script>
  const res = [
    {"name":"小明", "age":16, "marry":"单身"},
    {"name":"小花","age":15, "marry":"有男朋友"},
    {"name":"小胖","age":15, "marry":"有女朋友"},
    {"name":"小丽","age":15, "marry":"单身"}
  ];
  document.getElementById('person').innerHTML = template('tpl', {data:res}); 
  // 其实这里是把数组转为对象的形式传进的
</scrtip>

template

<script type="text/html" id="tpl">
  //写法一
  {{each data}}
  <li>{{$index}}索引 我叫{{$value.name}},今年{{$value.age}}岁,{{$value.marry}}</li>
  {{/each}}

  //写法二
  {{each data item index}}
  <li>{{index}}索引 我叫{{item.name}},今年{{item.age}}岁,{{item.marry}}</li>
  {{/each}}
</script>

下面在看数组渲染,这是一个数组

const res = ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'];

html

<div id="interest"></div>

js

<script>
  const res = ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'];
  document.getElementById('interest').innerHTML = template('tpl', {data:res});
  // 其实这里是把数组转为对象的形式传进的
</scrtip>

template

<script type="text/html" id="tpl">
  //写法一
  {{each data}}
  <li>{{$index}}索引 我喜欢{{$value.name}}</li>
  {{/each}}

  //写法二
  {{each data item index}}
  <li>{{index}}索引 我喜欢{{item}}</li>
  {{/each}}
</script>

就说这么多吧,其实这种模板用着挺简单的很顺手。

在软件开发中,MVC或者MVVM是经常被用到的设计模式。在web前端开发中,之前我们需要自己写许多代码来完成这项功能。而现在有许多优秀的类库可以帮我们实现这个功能。 许多优秀的前端框架都提供了强大的数据双向绑定的功能。比如 Vue.js, Angular.js, KnockoutJS。 如果我们在一些小型的项目中,只是希望某个功能区域有数据双向绑定的功能,是不是就非得使用这么重的框架呢?事实上,我们可以用jQuery来实现一个简单的数据双向绑定的功能。 从头开始做一个数据双向绑定并不是那么复杂。简单来说,需要实现下面三点: 我们需要指定View中的UI元素和数据中的属性对应关系。 我们需要监听View中的UI元素内容以及数据的变化。 最后就是我们需要把变化通知到所有与之绑定的数据或者UI元素。 Javascript Code

function DataBinder (objectId) {
  // 使用jQuery空对象作为监听对象
  var pubSub = jQuery({});
  //
  var dataAttr = 'bind-' + objectId;
  var message = objectId + ':change';
  // 监听dom中所有元素的 data-binding 属性变化。并由pubSub来处理。
  $(document).on('input change', '[data-' + dataAttr + ']', function (event) {
    var $ele = $(this);
    console.log('$ele', $ele);
    pubSub.trigger(message, [$ele.data(dataAttr), $ele.val()]);
  });
  // pubSub把数据变化推送给所有与之绑定的页面元素
  pubSub.on(message, function (event, proName, newValue) {
    $('[data-' + dataAttr + '=' + proName + ']').each(function () {
      var $ele = $(this);
      if($ele.is('input, textarea, select')) {
        $ele.val(newValue);
      } else {
        $ele.html(newValue);
      }
    })
  });
  return pubSub;
}
function User(uid) {
    var binder = new DataBinder(uid);
    var user = {
      attributes: {},
      set: function (attrName, val) {
        this.attributes[attrName] = val;
        binder.trigger(uid + ':change', [attrName, val, this]);
      },
      get: function (attrName) {
        return this.attributes[attrName];
      },
      _binder: binder
    }
  return user;
}

调用的时候,用uid与之关联。 Javascript Code

var user = new User('user');
$('#btnSet').bind('click', function (event) {
  user.set('name', 'Liuyuan211');
});

Html

<div class="item">
<label>用户名:</label><input type="text" data-bind-user="name" /><span data-bind-user="name"></span>
</div>
<div class="item">
<input type="button" id="btnSet" value="Set" />
</div>

该例子中,uid就是 data-bind-user=”name” 中的 user ,绑定的页面元素会自动与user对应的属性关联。

这是一个CSS变量(正式称为“ CSS自定义属性 ”) html

css

:root {
–mouse-x: 0px;
–mouse-y: 0px;
}

你可以用它们来设定一个位置: css

.mover {
left: var(–mouse-x);
top: var(–mouse-y);
}

如果要从JavaScript更新这些值,您需要: js

let root = document.documentElement;
root.addEventListener(“mousemove”, e => {
root.style.setProperty(‘–mouse-x’, e.clientX + “px”);
root.style.setProperty(‘–mouse-y’, e.clientY + “px”);
});

向HTML表单添加验证将确保用户以正确的格式准确地输入数据。在过去,验证表单输入需要使用JavaScript插件,但是现在大多数浏览器都有可以处理大部分验证的内置解决方案。 在本教程中,我们将向您展示如何仅使用本地HTML输入属性向表单添加验证规则。 项目概览 为了演示创建验证规则的过程,我们准备了一个简单的HTML注册表单Bootstrap 4。你可以点击下面的图片来打开一个现场演示。 布局 HTML 我们的设计包括一个带有两个输入字段和一个提交按钮的引导表单。在本例中,我们使用了3种不同类型的输入字段-文本输入、密码输入和电子邮件输入。

Create your account

CSS 我们还添加了一些基本的CSS样式,以使表单更加简单。

html {
background-color:#214c84;
background-blend-mode:overlay;
display:flex;
align-items:center;
justify-content:center;
height:100%;
}

body {
background-color:transparent;
}

.registration-form {
padding:50px 0;
}

.registration-form form {
max-width:800px;
padding:50px 70px;
border-radius:10px;
box-shadow:4px 4px 15px rgba(0, 0, 0, 0.2);
background-color:#fff;
}

.registration-form form h3 {
font-weight:bold;
margin-bottom:30px;
}

.registration-form .item {
border-radius:10px;
margin-bottom:25px;
padding:10px 20px;
}

.registration-form .create-account {
border-radius:30px;
padding:10px 20px;
font-size:18px;
font-weight:bold;
background-color:#3f93ff;
border:none;
color:white;
margin-top:20px;
}

@media (max-width: 576px) {
.registration-form form {
padding:50px 20px;
}
}

验证类型 HTML 5提供了一种使用输入属性进行内联验证的好方法。有大量的属性可用,我们将只看一些最常见的。要获得完整的列表,您可以访问这个优秀的MDN指南. required 此属性指定输入字段不能为空。它要求用户在提交表单之前输入一些内容。

maxlength 和 minlength 指定用户可以在输入字段中输入的最大/最小符号数。这在密码字段中尤其有用,因为更长的密码意味着更安全的密码。

pattern 指定必须匹配以传递输入数据的正则表达式。它可以与以下输入类型一起使用:文本、搜索、url、电子邮件和密码。

今天我们将使用CSS 3 gradients技术创建一个好看的带有斜角的选项卡面板。 下面就直接上代码

HTML

tab1 - content
tab2 - content
tab3 - content
tab4 - content

CSS

#tabs {
overflow: auto;
width: 100%;
list-style: none;
margin: 0;
padding: 0;
}

#tabs li {
margin: 0;
padding: 0;
float: left;
}

#tabs a {
box-shadow: -4px 0 0 rgba(0, 0, 0, .2);
background: #ad1c1c;
background: linear-gradient(225deg, transparent 10px, #ad1c1c 10px);
text-shadow: 0 1px 0 rgba(0,0,0,.5);
color: #fff;
float: left;
font: bold 12px/35px ‘Lucida sans’, Arial, Helvetica;
height: 35px;
padding: 0 30px;
text-decoration: none;
}

#tabs a:hover {
background: #c93434;
background: linear-gradient(225deg, transparent 10px, #c93434 10px);
}

#tabs a:focus {
outline: 0;
}

#tabs #current a {
background: #fff;
background: linear-gradient(225deg, transparent 10px, #fff 10px);
text-shadow: none;
color: #333;
}

#content {
background-color: #fff;
background-image: linear-gradient(top, #fff, #ddd);
border-radius: 0 2px 2px 2px;
box-shadow: 0 2px 2px #000, 0 -1px 0 #fff inset;
padding: 30px;
}

/* 这里的高度可随意*/
#content div {
height: 220px;
}

jQuery

下面的代码可能不是最好的,但我认为它相当不错

$(document).ready(function() {
$(“#content div”).hide(); // 最初隐藏所有内容
$(“#tabs li:first”).attr(“id”,”current”); // 激活第一个选项卡
$(“#content div:first”).fadeIn(); // 显示第一个标签内容

$(‘#tabs a’).click(function(e) {
e.preventDefault();
$(“#content div”).hide(); // 隐藏所有内容
$(“#tabs li”).attr(“id”,””); // 重置Id
$(this).parent().attr(“id”,”current”); // 这里点击后激活
$(‘#’ + $(this).attr(‘title’)).fadeIn(); // 显示当前选项卡的内容
});
})();