Sultana Postscript: pure css can write col, select, datepicker, carousel ...

To be continued

background

Today, more and more developed css3, focus-within attributes have already begun to be supported in Chrome. If there are outstanding css knowledge, a little ps skills, you can also use css3 with native html tag write good framework. Css3 through practice, I found custom native controls is not difficult, then wrote a small test chopper pure CSS3 Design achieve Material .

on

All the code for this article about the realization, as well as more pure css controls, please https: //github.com/Seasonley / ... View in.
In this paper, I developed a pure css framework Sultana conducted in several important common components in-depth analysis, we explore how the idea of a step by step implementation, including:

  1. var (- x) Write a grid system
  2. focus-within & a & input selection controls write Pull
  3. input radio & date to achieve date selection control
  4. background linear-gradient: a controversial scroll_indicator implementation
  5. + css css animation adaptive variable write size carousel controls
  6. The navigation bar: focus-within slide-out sidebar navigation
  7. The navigation bar: summary folding navigation, static style spike bulma
  8. input range can write five-star praise friends
  9. Friendly tooltip, transform Dafa

1.var (- x) Write a grid system ( source )

As we all know Bootstrap grid system provides 12 different devices under the grid width, then how do we beat Bootstrap, achieve a powerful adaptive grid with css3 variables?

1.1 Statement css variable names different devices

Suppose we consider four kinds of apparatus side table shown below. Bootstrap we will follow them named sm, md, lg.

on-col Special small screen (-, 480px) Small screen (480px, 720px) The screen (720px, 1200px) Big screen (1200px, +) Fixed value (covering the above variables)
css variable name --sm --md --lg --col
Types of int(1 , 2 , ... , 12) int(1 , 2 , ... , 12) int(1 , 2 , ... , 12) number(90% , 0.3 , ...)

So colwhat? The width of the final container should be converted into a single variable, the front by 3 are secondary. Suppose we layout is as follows

<div su-row>
    <div su="primary" su-col style="--sm:3;--md:4;--lg:12;--sm-v:hidden"></div>
    <div su="light" su-col style="--sm:3.2;--md:4.5;--lg:12;"></div>
    <div su="info" su-col style="--sm:3.3;--lg:12;"></div>
</div>
<div su-row>
    <div su="warning" su-col style="--col:0.22;--sm-d:none"></div>
    <div su="info" su-col style="--col:0.33;"></div>
    <div su="primary" su-col style="--col:0.44;"></div>
</div>  

1.2 --col: calc (var (- m) / 12)

We want different widths col apparatus according to an adaptive variable, you can also have displayand visiblitythese auxiliary operations, implemented css then look to -mdas an example, as follows.

@media screen and (min-width: 721px) {
    div[su-col] {
        --col: calc(var(--md) / 12);
        display: var(--md-d);
        visibility: var(--md-v);
    }
}

Var then just used in the su-col (- col) can get adaptation. code show as below.

div[su-col] {
 width: calc(100% * var(--col));
}

Is not very easy, each row is the essence. If the direct use of --colthat adaptation variable failure, which is usually used without the need for adaptation scene.
image description

1.3 flex layout shorthand

flex layout gradually replace floating layout, then the custom class some of shorthand to make the code look cleaner is also very necessary. I provide a way to achieve, not necessarily popular, are not interested can skip.

Referring to flex attribute Abbreviations :

  • j=justify,a=algin,c=content
  • 100,001,010,101=start,end,center,between
  • -row=row-reverse
  • -warp=warp-reverse
  • !warp=no-warp

html example

clipboard.png

2. focus-within & a & input pull-write selection control ( source )

2.1focus-within so with

看这个标题就秘制重量级,下拉控件不好办,很多css框架都只能div套啊套的,再用js搞点数据绑定。不过既然有focus-within。我们先脑补一下,点击这个a标签,a+div里的input[radio]都显示,不focus则隐藏。这解决了下拉动画效果。那么鼠标经过要高亮,input又不能写文字,也没有伪元素可以弄dataset,那只好input+span组合一下了。假设html部分代码如下。

<button su="outlined -">
    <a href="javascript:">(blank)</a>
    <ul>
        <input checked type="radio" name="ra" value=""/>
        <span>(blank)</span>
        <input title="A.dada" type="radio" name="ra" value="1"/>
        <span>A.da</span>
        <input title="B.huha" type="radio" name="ra" value="2"/>
        <span >B.la</span>
    </ul>
</button>

这样看来似乎能写个导航栏了呢,多个按钮拼一下什么的。

2.2选中的移到最上面

如标题,接下来解决选中项的显示,很简单,absolute绝对定位嘛。

button[su~="-"] input:checked+span {
    position: absolute;
    top: 0px;
}

image description

默认来个value=""的,文字为(blank),算是很尴尬的委屈求全了,缺点是选中项不再在下拉列表中显示了,其次文字是不能点击选中的,只能点空白处。

3. input radio & date 实现日期选择控件 (源码)

3.1 31个input

有意思,看完上面的奇葩实现select,你应该对这个更感兴趣一点。作为一个前端你不会自己写日期控件,你好意思吗你?整天用jquery-datepicker你的良心不会痛吗?这回我们再尬一回,用css和少量的js代码来实现。尬在哪呢?31个input[radio],谁会用啊,可能只有那些禁用js的浏览器的需求方需要这个。

3.2 少量的js

oninput的时候需要算出闰年+这个月1号星期几,把它放到dataset,由css枚举1号的7种星期情况,css枚举大月小月和闰年2月。(这行描述最重要)
代码实现如下

html

<form oninput="ymd.value=y.value+'-'+('0'+m.value).slice(-2)+'-'+d.value;ymd.dataset.leap=(y.value % 4 == 0) && (y.value % 100 != 0 || y.value % 400 == 0);ymd.dataset.day=new Date(y.value+'-'+('0'+m.value).slice(-2)+'-1').getDay()" 
onclick="ymd.value=y.value+'-'+('0'+m.value).slice(-2)+'-'+d.value"
onmouseover="ymd.dataset.day=new Date(y.value+'-'+('0'+m.value).slice(-2)+'-1').getDay()">
    <label su-date>
            <input su type="date" name="ymd" readonly>
            <div>
                <input name="y" type="number" min="1970" max="3000" value="2000" 
                onchange="this.setAttribute('value', this.value)">
                <input name="m" type="number" min="1" max="12" value="1" 
                onchange="this.setAttribute('value', this.value)">
                <div>
                    <input name="d" type="radio" value="01" checked>
                    <input name="d" type="radio" value="02">
                    ...
                    

css

label[su-date] input[type="number"][value="2"]+div input[type="radio"]:last-of-type,
label[su-date] input[type="number"][value="4"]+div input[type="radio"]:last-of-type,
label[su-date] input[type="number"][value="6"]+div input[type="radio"]:last-of-type,
label[su-date] input[type="number"][value="9"]+div input[type="radio"]:last-of-type,
label[su-date] input[type="number"][value="11"]+div input[type="radio"]:last-of-type,
label[su-date] input[type="number"][value="2"]+div input[type="radio"][value="30"],
label[su-date] input[type="number"][value="2"]+div input[type="radio"][value="29"] {
    display: none
}

label[su-date] input[name="ymd"][data-leap="true"]+div input[type="radio"][value="29"] {
    display: block
}

label[su-date] input[name="ymd"][data-day="1"]+div input[type="radio"][value="01"] {
    margin-left: calc(0 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="2"]+div input[type="radio"][value="01"] {
    margin-left: calc(1 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="3"]+div input[type="radio"][value="01"] {
    margin-left: calc(2 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="4"]+div input[type="radio"][value="01"] {
    margin-left: calc(3 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="5"]+div input[type="radio"][value="01"] {
    margin-left: calc(4 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="6"]+div input[type="radio"][value="01"] {
    margin-left: calc(5 * var(--x2))
}

label[su-date] input[name="ymd"][data-day="0"]+div input[type="radio"][value="01"] {
    margin-left: calc(6 * var(--x2))
}

缺点:老长老长的html和css...
预览:
image description

4. background linear-gradient:一个有争议的scroll_indicator实现方式

在掘金上看到网易考拉前端写的CSS Scroll Indicator —— 纯CSS 滚动指示器,实现方式很巧妙,通过直角三角形背景的顶部界面与页面高度相关性制造一个实际上滚背景,看起来在伸缩进度条的效果。该文提到已知的2个缺点。

  1. 文档内容太少(高度太小)的话,进度条呈箭头形,不美观(可考虑加毛玻璃效果来弱化)
  2. background-size: 100% calc(100% - 99vh); 中的99vh是相对值,若是视窗高度比较小,进度条会填不满进度条槽(可考虑加min-height来弱化)

那它放到实际项目中效果如何呢,本人试验了一下,在篇幅很长,标签元素嵌套很多的页面中加入scroll_indicator,滚动过程中背景重绘十分卡,以至于元素按钮点开都不能及时响应。所以如果是纯文本博客或者说明文档之类的元素标签和css足够少的情况下,可以使用该方式实现静态文档的进度条,复杂的dom和css情况下不建议使用。当本人放到自己项目中测试时,按住滚动条上下快速拖动时,滚动条都是跳帧的。。。

5. css动画 + css变量 写自适应大小轮播控件 (源码)

Bootstrap轮播控件通过js实现,那么css能实现吗,显然是可以的。实现到什么程度呢?本人枚举以下可以实现功能:

  1. 自适应屏幕,宽高可控
  2. 轮播图片有单独的自定义标题标签(不能是伪元素)
  3. 要有圆点指示器,圆点大小可自定义,高亮的圆点代表滚动到第几章图
  4. 指示器可点击,跳转到对应的图
  5. 鼠标hover在控件上暂停轮播

看上去很全了,本人讲一下具体思路。
轮播需要假设在absolute的画布上横向滚动,改变元素的水平位移数值margin-left来实现。通过css关键帧动画能完成。如下:

@keyframes rua {
     0%,20% {margin-left: 0}
    25%,40% {margin-left: calc(0px - 1*var(--w))}
    45%,60% {margin-left: calc(0px - 2*var(--w))}
    65%,80% {margin-left: calc(0px - 3*var(--w))}
    85%,100%{margin-left: calc(0px - 4*var(--w))}
}

指示器可以同新标签,但不能像标题元素包裹在图片容器内,因为指示器是不能滚动的。于是绝对定位相对于整个控件容器内就可以。html代码如下:

<aside su="." style="--w:400px;--h:300px;--p:20px;">
    <button></button><button></button>
    <button></button><button></button>
    <button></button>
    <ul>
        <li style="background:gray;"><a>标题1</a></li>
        <li style="background:orange;"><a>标题2</a></li>
        <li style="background:teal;"><a>标题3</a></li>
        <li style="background:blue;"><a>标题4</a></li>
        <li style="background:black;"><a>标题5</a></li>
    </ul>
</aside>

在上述5点功能中,
<1><3>可以用css变量解决,比如--w:400px;--h:300px;--p:20px;实现了宽度400px,高度300px,圆点大小直径20px的控件。
<2>单独设a标签
<4>用focus-within实现点击后css动画暂停在某个关键帧,缺点一是:有几个图就要写几个动画,缺点二是:点击后虽然选中了,但鼠标移出控件不会继续滚动,在控件外点击会跳回初始动画关键帧。以一个图的动画为例:

aside[su~="."] button:nth-child(5):focus-within~ul {
    animation: ma5 .5s ease-out forwards;
}
@keyframes ma5 {
    100% {margin-left: calc(-4 * var(--w))}
}

<5>通过hover的暂停css动画来控制

aside[su~="."] button:hover,
aside[su~="."] ul:hover {
    will-change: transform;
    animation-play-state: paused;
}

整体效果还不错:
image description

6. 导航栏之:focus-within 侧边栏导航滑出 (源码)

在没出现focus-within之前,用临近元素选择器+css能实现纯css的下拉选项的导航栏,在这里就不多展开了。最后一个focus-within的魔法魅力。我们需要实现类似android侧边栏滑出的效果。
image description

网上已经有人实现了《CSS :focus-within》 Airen的博客,那我就讲一下他是如何实现的。该文中用到了移动端延伸出的冷门css属性touch-action: manipulation。CSS属性 touch-action 用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动、缩放等)(MDN)。移动端300ms延迟,就可以使用 touch-action: manipulation; 来解决。我们只需要实现点击左上角按钮后滑出菜单,声明一下按钮点击不影响其手势操作就行了。

本控件只要实现focus-within后动画弹出菜单。失去焦点的时候弹回去就行了。其实和touch-action没什么关系。先定义菜单部分的css,将其扔到左边屏幕外(margin或者transform都行):

#nav-content
transform: translateX(-100%);
transition: transform .3s;

再定义选中后的菜单:

#nav-container:focus-within #nav-content {
    transform: none;
}

大致思路就是这样。讲了那么多focus-within的相关内容,但国内部分webkit内核浏览器还在50以下的阶段,还请各位使用chrome63以上版本访问。

7. 导航栏之:summary折叠导航,秒杀bulma静态样式 (源码)

先来看看 bulma 是怎么写的
clipboard.png

ul li p a 相互嵌套,没错是个很好的实现方式,如果加focus-within和相邻元素选择也能实现点击后的动画效果,不过要稍微改变一下嵌套方式,但这不是本文的讨论重点。focus-within有它的缺点,对于一个菜单来说,用户好不容易展开找到了,一点别的菜单层级,之前的全缩回去了,那怎么行。必须要有一个展开后点击再缩回去的功能。

这就要引出神奇的summary标签,只用配合details用时,当details内的summary元素被点击时,details全部显示,再次点击缩起只剩summary。在张鑫旭大神的借助HTML5 details,summary无JS实现各种交互效果中提到了很多可实现的控件,树,菜单等等。

本人仿照Bulma用summary特性实现了一个带动画的导航菜单,代码还算优雅,如下图所示。
image description

8. input range 可以写五星好评啦 (源码)

A native range of input controls, the browser is very simple, and there is someone to go with wood native. We look at the ants gold dress front-end team is how to achieve ( ant.desgin ):

image description

Looks like section>ul>li, plus class represents a zero fullsmall star, moved up as well as animation, but also a bunch of class. Let us not consider implementing animation, first to Tucao rendering performance issues class after the dom more, li inside there are two and a half little stars to support step=0.5scoring, these native browsers support the attributes why use 2 + 5 * 3 = 17 dom element generation? Handle and a spout lip off, and quickly pulled out a code to yo.

First, html, on line ~

<input su="star" value="1" min="1" max="5" type="range" onchange="this.setAttribute('value', this.value)" />

Followed css:

input[type="range"][su~="star"] {
    cursor: pointer;width: calc(16px * 5);height: 16px;
    -webkit-appearance: none;-webkit-mask-image: var(--star);
    background: linear-gradient(to right, var(--Primary), var(--Primary)), 
                linear-gradient(to right, var(--Gray), var(--Gray));
    background-repeat: no-repeat;
}

input[type="range"][su~="star"][value="1"] {
background-size: calc(16px * 1) 16px, calc(16px * 5) 16px;
}

input[type="range"][su~="star"][value="2"] {
    background-size: calc(16px * 2) 16px, calc(16px * 5) 16px;
}
...

By input different attributes background, little star will show different color, linear-gradientrendering the progress, if it is a half stars also easy to handle, in step=0.5the case of multi-enumerate a few cases .5 points on the line. Results are as follows:
image description

9. friendly tooltip, transform Dafa ( source )

transformIn the implementation mentioned above android sliding menu, and then expanded at its other uses. We can use to write tooltip. For a titletag attribute, a well known mouse suspended displays block, content titleattribute. Then the pseudo-element content: attrjust to fit transformconstruction tooltip different directions.

[su-hint~="bottom"]:after {
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
}

[su-hint~="bottom"]:hover:after {
    transform: translateX(-50%) translateY(8px);
}

[su-hint~="right"]:after {
    margin-bottom: -14px;
    left: 100%;
    bottom: 50%;
}

[su-hint~="right"]:hover:after {
    transform: translateX(8px);
}

image description

on github already powerful custom tooltip, if you are willing to sacrifice before aftertwo pseudo-elements to achieve bubbles and arrows tooltip, it is recommended to use hint.css

Guess you like

Origin www.cnblogs.com/homehtml/p/11932177.html