css skeleton & web app skeleton
css skeleton & web app skeleton
skeleton / 骨架屏
https://www.cnblogs.com/xgqfrms/p/10437258.html
https://github.com/dhg/Skeleton/
https://codepen.io/xgqfrms/pen/zQEJWw
https://codepen.io/xgqfrms/details/zQEJWw
https://codepen.io/xgqfrms/full/zQEJWw
https://github.com/dhg/Skeleton/
https://github.com/whatsnewsaes/Skeleton-Sass
skeleton screens 💀
https://css-tricks.com/building-skeleton-screens-css-custom-properties/
.skeleton {
background-repeat: no-repeat;
background-image:
/* layer 2: avatar */
/* white circle with 16px radius */
radial-gradient(circle 16px, white 99%, transparent 0),
/* layer 1: title */
/* white rectangle with 40px height */
linear-gradient(white 40px, transparent 0),
/* layer 0: card bg */
/* gray rectangle that covers whole element */
linear-gradient(gray 100%, transparent 0);
}
.skeleton {
background-size:
32px 32px, /* avatar */
200px 40px, /* title */
100% 100%; /* card bg */
}
.skeleton {
background-position:
24px 24px, /* avatar */
24px 200px, /* title */
0 0; /* card bg */
}
Custom CSS properties & css var
https://www.smashingmagazine.com/2017/04/start-using-css-custom-properties/
.skeleton {
/*
define as separate properties
*/
--card-height: 340px;
--card-padding:24px;
--card-skeleton: linear-gradient(gray var(--card-height), transparent 0);
--title-height: 32px;
--title-width: 200px;
--title-position: var(--card-padding) 180px;
--title-skeleton: linear-gradient(white var(--title-height), transparent 0);
--avatar-size: 32px;
--avatar-position: var(--card-padding) var(--card-padding);
--avatar-skeleton: radial-gradient(
circle calc(var(--avatar-size) / 2),
white 99%,
transparent 0
);
/*
now we can break the background up
into individual shapes
*/
background-image:
var(--avatar-skeleton),
var(--title-skeleton),
var(--card-skeleton);
background-size:
var(--avatar-size),
var(--title-width) var(--title-height),
100% 100%;
background-position:
var(--avatar-position),
var(--title-position),
0 0;
}
http://caniuse.com/#feat=css-variables
@media screen and (min-width: 47em) {
:root {
--card-padding: 32px;
--card-height: 360px;
}
}
Animation
<div class="card"></div>
/*
* Variables
*/
:root {
--card-padding: 24px;
--card-height: 340px;
--card-skeleton: linear-gradient(lightgrey var(--card-height), transparent 0);
--avatar-size: 32px;
--avatar-position: var(--card-padding) var(--card-padding);
--avatar-skeleton: radial-gradient(circle 16px at center, white 99%, transparent 0
);
--title-height: 32px;
--title-width: 200px;
--title-position: var(--card-padding) 180px;
--title-skeleton: linear-gradient(white var(--title-height), transparent 0);
--desc-line-height: 16px;
--desc-line-skeleton: linear-gradient(white var(--desc-line-height), transparent 0);
--desc-line-1-width:230px;
--desc-line-1-position: var(--card-padding) 242px;
--desc-line-2-width:180px;
--desc-line-2-position: var(--card-padding) 265px;
--footer-height: 40px;
--footer-position: 0 calc(var(--card-height) - var(--footer-height));
--footer-skeleton: linear-gradient(white var(--footer-height), transparent 0);
--blur-width: 200px;
--blur-size: var(--blur-width) calc(var(--card-height) - var(--footer-height));
}
/*
* Card Skeleton for Loading
*/
.card {
width: 280px; //demo
height: var(--card-height);
&:empty::after {
content:"";
display:block;
width: 100%;
height: 100%;
border-radius:6px;
box-shadow: 0 10px 45px rgba(0,0,0, .1);
background-image:
linear-gradient(
90deg,
rgba(lightgrey, 0) 0,
rgba(lightgrey, .8) 50%,
rgba(lightgrey, 0) 100%
), //animation blur
var(--title-skeleton), //title
var(--desc-line-skeleton), //desc1
var(--desc-line-skeleton), //desc2
var(--avatar-skeleton), //avatar
var(--footer-skeleton), //footer bar
var(--card-skeleton) //card
;
background-size:
var(--blur-size),
var(--title-width) var(--title-height),
var(--desc-line-1-width) var(--desc-line-height),
var(--desc-line-2-width) var(--desc-line-height),
var(--avatar-size) var(--avatar-size),
100% var(--footer-height),
100% 100%
;
background-position:
-150% 0, //animation
var(--title-position), //title
var(--desc-line-1-position), //desc1
var(--desc-line-2-position), //desc2
var(--avatar-position), //avatar
var(--footer-position), //footer bar
0 0 //card
;
background-repeat: no-repeat;
animation: loading 1.5s infinite;
}
}
@keyframes loading {
to {
background-position:
350% 0,
var(--title-position),
var(--desc-line-1-position),
var(--desc-line-2-position),
var(--avatar-position),
var(--footer-position),
0 0
;
}
}
/*
* Demo Stuff
*/
body {
min-height:100vh;
background-color:#FFF;
display:flex;
justify-content:center;
align-items:center;
}
:empty selector & pseudo element
CSS & Card Skeleton
https://codepen.io/xgqfrms/pen/KLXrob
https://codepen.io/xgqfrms/pen/gJGQeX
web app demos
https://cangdu.org/elm/#/shop?geohash=31.278702,121.465513&id=3276
CSS Pseudo Selectors
::slotted & :empty
https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
https://developer.mozilla.org/en-US/docs/Web/CSS/:empty
/* Selects any element placed inside a slot */
::slotted(*) {
font-weight: bold;
}
/* Selects any <span> placed inside a slot */
::slotted(span) {
font-weight: bold;
}
https://css-tricks.com/building-skeleton-screens-css-custom-properties/
-
You can use the
:empty
selector and a pseudo element to draw the skeleton, so it only applies to empty card elements.Once the content is injected, the skeleton screen will automatically disappear.
/* css skeleton */
/*
* Card Skeleton for Loading
*/
.card {
width: 280px; //demo
height: var(--card-height);
&:empty::after {
content:"";
display:block;
width: 100%;
height: 100%;
border-radius:6px;
box-shadow: 0 10px 45px rgba(0,0,0, .1);
background-image:
linear-gradient(
90deg,
rgba(lightgrey, 0) 0,
rgba(lightgrey, .8) 50%,
rgba(lightgrey, 0) 100%
), //animation blur
var(--title-skeleton), //title
var(--desc-line-skeleton), //desc1
var(--desc-line-skeleton), //desc2
var(--avatar-skeleton), //avatar
var(--footer-skeleton), //footer bar
var(--card-skeleton) //card
;
background-size:
var(--blur-size),
var(--title-width) var(--title-height),
var(--desc-line-1-width) var(--desc-line-height),
var(--desc-line-2-width) var(--desc-line-height),
var(--avatar-size) var(--avatar-size),
100% var(--footer-height),
100% 100%
;
background-position:
-150% 0, //animation
var(--title-position), //title
var(--desc-line-1-position), //desc1
var(--desc-line-2-position), //desc2
var(--avatar-position), //avatar
var(--footer-position), //footer bar
0 0 //card
;
background-repeat: no-repeat;
animation: loading 1.5s infinite;
}
}
@keyframes loading {
to {
background-position:
350% 0,
var(--title-position),
var(--desc-line-1-position),
var(--desc-line-2-position),
var(--avatar-position),
var(--footer-position),
0 0
;
}
}
©xgqfrms 2012-2020
www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/10898804.html
未经授权禁止转载,违者必究!