一直以来对前端抱有莫名的兴趣, 这次换工作后如愿以偿的接手了很多前端的任务. 借着之前粗浅的经验上手的还算快, 可是深入的方面就不太跟得上了. 众所周知, 前端的学习离不开实践和积累, 为了快速而有效的进步, 在此制定了第一阶段的学习任务 -- 收集和实现 CodePen 上 100 个前端小项目. 此阶段的目的是借着一个个小项目快速熟悉 html, CSS, JS 的简单应用和套路.
下面开始进入正题, 第一个项目是我在 CodePen 上看到的, 觉得图案可爱就把代码扒了下来实现了一遍 (图案见下图). 这个项目精髓主要在于 CSS, 研究完这个项目, 基本上可以对 CSS 盒模型, 瀑布流模式, DOM 分层有基本的掌握.
https://codepen.io/xinxhe/pen/PooQNXJ?editors=1100
image.PNG
下面是 HTML 的实现, 这里是用了 pug, 语法上更简洁. 可以看出, HTML 元素的分层是自外向内的, 最外面是一个大的 container, 向内一层分为了三个大块: 笑脸, 下划线, 和背景装饰物, 再向内就是三大块中的各种细节.
- div.container
- div.smiley__face.smiley__face--01 // 笑脸中间
- div.face
- div.eyes
- div.eye.eye__left
- div.eye.eye__right
- div.mouth
- div.smiley__face.smiley__face--02 // 笑脸左边
- div.face
- div.eyes
- div.eye.eye__left
- div.eye.eye__right
- div.mouth
- div.smiley__face.smiley__face--03 // 笑脸右边
- div.face
- div.eyes
- div.eye.eye__left
- div.eye.eye__right
- div.mouth
- div.underground // 下划线
- div.sparkles // 星星和圈圈
- div.star.star--01
- div.star.star--02
- div.star.star--03
- div.circle.circle--01
- div.circle.circle--02
- div.circle.circle--03
- div.circle.circle--04
CSS 的实现比较长, 直接上注释解释.
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box; // padding 和 border 的宽度包含在 width 和 height 中
- }
- body {
- display: block;
- width: 100%;
- height: 100vh; // 1vh 代表浏览器 viewport 高度的 1%. Viewport 代表浏览器窗口的大小, 如果拖动浏览器边框, 浏览器的 viewport 会根据窗口边界的拖动而改变大小.
- background: #ecf0f1;
- }
- .container {
- position: relative; // 相对于正常位置. 在这里, container 的位置确定是相对于 body 的元件的.
- display: flex; // 盒模型, 可以定义其子组件的排列方式
- width: 100%;
- height: 100vh;
- justify-content: center; // Horizontal alignment, 水平居中
- align-items: center; // Vertical alignment, 垂直居中
- .smiley__face {
- padding: 10px;
- position: absolute; // 元件的位置是相对于最近的 positioned 的父元件来确定的. Positioned 的元件是指任何具有 position 属性但是其值不是 static 的父元件. 在这里, smiley__face 的位置是相对于 container 来定的.
- display: flex;
- align-items: flex-start; // 垂直靠顶端排列
- justify-content: center;
- border: 12px solid #2c3e50;
- width: 170px;
- height: 190px;
- background: #ffffff;
- border-radius: 15px;
- overflow: hidden;
- .face {
- background: #f1c40f;
- width: 100%;
- height: 120px;
- border-radius: 5px;
- display: flex;
- flex-direction: column; // 定义子元件们的排列方式为竖直的一列.
- justify-content: center;
- align-items: center;
- position: relative; // 位置定义相对于 smiley__face, 因为 smiley__face 有 position 的属性 (并且值不是 static), 并且是最近的父元件
- overflow: hidden;
- z-index: 1; // z-index 定义了层级关系, 数字越大层级越高
- .eyes {
- display: flex;
- justify-content: space-between; // 定义了子元件们之间间隔的平均排列方式
- align-items: center;
- height: 20px;
- width: 60%;
- .eye {
- display: block;
- width: 15px;
- height: 15px;
- background: #2c3e50;
- border-radius: 50px;
- }
- }
- .mouth {
- display: block;
- width: 32px;
- height: 20px;
- background: #2c3e50;
- border-top-left-radius:15px;
- border-top-right-radius:15px;
- border-bottom-left-radius:50px;
- border-bottom-right-radius:50px;
- position: relative;
- overflow: hidden;
- &::before { // 舌头
- content: "";
- display: block;
- width: 20px;
- height: 10px;
- background: #e74c3c;
- border-radius:50%;
- position: absolute;
- left: 50%;
- bottom: 2px;
- transform: translateX(-50%); // Move 50% of the width of the element
- }
- }
- }
- &.smiley__face--01 {
- z-index: 3;
- }
- &.smiley__face--02,
- &.smiley__face--03 {
- z-index: 2;
- }
- &.smiley__face--02 {
- transform: rotate(-25deg) translate(-100px, -8px) scale(.9);
- .face {
- background: #3498db;
- &::before { // 脸部非阴影部分
- content: "";
- position: absolute;
- left: 0;
- top: 0;
- display: block;
- width: 70%;
- height: 100%;
- background: #0abde3;
- z-index: -1;
- transform: skewX(-25deg) translateX(-30%);
- }
- }
- }
- &.smiley__face--03 {
- transform: rotate(25deg) translate(100px, -8px) scale(.9);
- .face { // 脸部非阴影部分
- background: #ff7f50;
- &::before {
- content: "";
- position: absolute;
- left: 0;
- top: 0;
- display: block;
- width: 70%;
- height: 100%;
- background:#ff6348;
- z-index: -1;
- transform: skewX(25deg) translateX(-30%);
- }
- }
- }
- }
- .underground {
- display: block;
- width: 200px;
- margin: 0 auto;
- border: 6px solid #2c3e50;
- position: relative;
- height: 1px;
- transform: translateY(180px);
- border-radius: 50px;
- }
- .sparkles {
- position: absolute;
- display: block;
- width: 500px;
- height: 80%;
- .star {
- display: block;
- width: 50px;
- height: 50px;
- margin: 20px;
- position: absolute;
- overflow: hidden;
- &::before { // 星星中横杠
- content: "";
- display: block;
- width: 80%;
- position: absolute;
- left: 0;
- top: 50%;
- transform: translate(0, -50%);
- border:4px solid #2c3e50;
- border-radius: 50px;
- }
- &::after { // 星星中竖杠
- content:"";
- display: block;
- height:80%;
- position: absolute;
- left:50%;
- top:50%;
- transform:translate(-50%,-50%);
- border:4px solid #2c3e50;
- border-radius:50px;
- }
- &.star--01 {
- top:10%;
- left:30%;
- transform:translate(-30%,-10%) scale(.4);
- &::before {
- border-color:#f1c40f;
- }
- &::after {
- border-color:#f1c40f;
- }
- &::before,
- &::after {
- border-width:6px;
- }
- }
- &.star--02 {
- top: 20%;
- left: 90%;
- transform: translate(-90%, -20%) scale(.3);
- &::before {
- border-color: #3498db;
- }
- &::after {
- border-color: #3498db;
- }
- &::before,
- &::after {
- border-width: 6px;
- }
- }
- &.star--03 {
- top: 2%;
- left: 60%;
- transform: translate(-60%, -2%) scale(.7);
- &::before {
- border-color: #ff7f50;
- }
- &::after {
- border-color: #ff7f50;
- }
- &::before,
- &::after {
- border-width: 5px;
- }
- }
- }
- .circle {
- display: block;
- width: 50px;
- height: 50px;
- border-radius: 50px;
- background: #f1c40f;
- position: absolute;
- &.circle--01 {
- border: 10px solid #f1c40f;
- background: transparent;
- top: 10%;
- left: 15%;
- transform: translate(-15%, -10%) scale(.5);
- }
- &.circle--02 {
- background: transparent;
- border: 15px solid #3498db;
- top: 40%;
- left: 100%;
- transform: translate(-100%, -40%) scale(.2);
- }
- &.circle--03 {
- background: #ff7f50;
- top: 30%;
- left: 8%;
- transform: translate(8%, -30%) scale(.3);
- }
- &.circle--04 {
- top: 70%;
- left: 0%;
- transform: translate(0%, -70%) scale(.2);
- }
- }
- }
- }
来源: http://www.jianshu.com/p/f767a8c71a27