CSS布局(五):从设计图到html页面

2,379 阅读6分钟

前言

这篇文章是CSS布局系列的第六篇文章。前面几篇文章简单介绍了CSS盒模型,CSS的几种布局模型。在这篇文章中,我想跟大家聊一下如何利用CSS和html将网页的设计图转换成实际可以在前端工程中使用的html和css资源,或者也可以说复现已有的网页页面结构。 还原网页框图.png
在如上图所示的框图中,html5+css3就是一个blackbox,我们需要做的事情就是解开这个blackbox的结构,使得输入和输出的静态网页页面看起来一模一样。

第一步:设计稿界面分区

要想还原页面,首先要做的就是将拿到的设计稿或者html页面进行分区。分区的方法是:

  1. 对页面划分区域,一般的网页都会有:标题栏、导航栏、主页面、侧边栏、脚注。第一步,需要把这几个元素都找出来
  2. 分别对每个元素进行分析,该元素由哪几部分组成,排列方向是怎样的 以掘金首页为例:

该页面的导航栏和标题栏是在一起的,在导航栏之后的部分是主页面和侧边栏,没有脚注。粗略划分之后的结果如下图所示: 接下来要做的事情是确定每个元素的布局方式

  • 标题栏/导航栏: 该页面的导航栏分为两个部分,如果点一下最上面的导航栏标签会发现,第二个导航栏的内容会根据第一个导航栏的标签变化而变化。这说明这两个导航栏之间有包含关系。每一个导航栏都是单行的排列,因此采用 flex 布局可以很方便的实现。
  • 主页面: 主页面是文章列表,它包含两个部分:热门/最新/热榜三个标签,文章简要信息的卡片。标签部分是由排成一行的三个小标签组成,它可以使用flex布局;文章简要信息的卡片,每一个的样式都是相同的,因此,CSS样式的代码只需要做好一个小卡片即可。文章的小卡片可以分为两列,左边的一列是文章的信息,右边的一列是文章的封面,可以使用flex布局。文章的信息又可以分为四行,第一行标明了文章的作者、日期,以及文章的标签;第二行是文章的题目,第三行是文章的简介;第四行标明浏览量、点赞量,以及评论的数目。关于这部分的布局,可以采用流式布局。
  • 侧边栏: 侧边栏有很多信息,但都是以小卡片的形式摆放在主页面的旁边。只需要把每一个部分都做好,然后按照文档流的布局方式放在这边即可。

第二步:html结构确定以及页面分区

在分析好设计图或者现成网页的布局之后就可以构建html骨架结构了。根据第一步分析的结果,html文件的结构如下:

<!DOCTYPE HTML>
<html>
    <head>
        <title>掘金首页复现</title>
    </head>
    <body>
        <!-- 导航栏 -->
        <div class="nav-bar">
            <div>掘金</div>
            <div>首页</div>
            <div>沸点</div>
            <div>资讯</div>
            ...
        </div>
        <div class="sub-nav-bar">
            <div>推荐</div>
            <div>关注</div>
            ...
        </div>
        
        <!-- 主页面容器 -->
        <div class="main-container">
        
            <!-- 主页面 -->
            <div class="main">
            
                <!-- 主页面的小标签 -->
                <div class="tags">
                    <div>热门</div>
                    <div>最新</div>
                    <div>热榜</div>
                </div>
                
                <!-- 文章列表的容器 -->
                <div class="article-container">
                    <div class="article-item">
                        <div class="aritcle-content>
                            <div class="article-info">
                                <div>作者</div>
                                <div>时间</div>
                                <div>标签</div>
                            </div>
                            <h2>文章标题</h2>
                            <p>文章简介</p>
                            <div class="article-count">
                                <div>浏览</div>
                                <div>点赞</div>
                                <div>评论</div>
                            </div>
                        </div>
                        <div class="article-cover">
                            <img>
                        </div>
                    </div>
                </div>
            </div>
            
            <!-- 侧边栏容器 -->
            <div class="aside-container">
            </div>
        </div>
    </body>
</html>

第三步:选择合适的布局模型

第二步的结果是一个比较丑的界面。如下图所示,所有的元素都挤在整个页面的小角落里。这一步,我们需要根据第一步的分析结果对这个页面添加布局和样式。 我个人的习惯是先由外到内的写布局,即先把外层的框架搭建起来,然后在往里面填元素,并且对背景、边框、边距这些参数进行调节。这就是一个体力活了,只能边写边看效果。这边只展示几个关键的代码.

  1. 文章列表卡片的代码:
  • html
<div class="article-item">                        
    <div class="article-item-info">
        <div class="article-info-author">椿湫</div>
        <div class="article-info-date">2021-07-07</div>
        <div class="article-info-tags">javascript · react · 前端</div>
    </div>
    <h2>react学习笔记(一)</h2>
    <p>这是一篇关于react的学习笔记,初步介绍了react的各种特性,以及如何安装,如何使用脚手架创建工程,构建前端项目,...</p>
    <div class="article-item-count">
        <div class="article-count-view">浏览:324</div>
        <div class="article-count-agree">点赞:6</div>
        <div class="article-count-comment">评论:5</div>
    </div>
</div>
  • css
.article-item {
    width: 95%;
    border-bottom: 1px solid #ccc;
    margin: 10px;   
    padding: 10px;

    display: flex;
    flex-direction: column;
    row-gap: 10px;
}

.article-item h2 {
    color: var(--border-color);
}

.article-item-info {
    display: flex;
    color: #ccc;
    font-size: 16px;
}

.article-info-author,
.article-info-date {
    margin-right: 10px;
    padding-right: 10px;
    border-right: 1px solid #ccc;
}
.article-info-author {
    color: #999;
}

.article-item-count {
    display: flex;
    column-gap: 20px;
    color: #999;
}
  1. 导航栏
  • html
<div class="blog-navbar-list">
    <div class="blog-navbar-item"><a href="#">网站首页</a></div>
    <div class="blog-navbar-item"><a href="#">前端技术</a></div>
    <div class="blog-navbar-item"><a href="#">生活分享</a></div>
</div>
  • css
.blog-navbar-list {
    display: flex;
    width: 50%;
    height: calc(var(--navbar-height) - (var(--navbar-border-width))*2);
    align-items: center;
    column-gap: 5px;
    position: relative;
    padding-left: 5px;
}
.blog-navbar-item {
    width: 20%; 
    height: calc(var(--navbar-height) - (var(--navbar-border-width))*2);
    /* background-color: turquoise;   */
    display: flex;
    justify-content: center;
    align-items: center;
}

.blog-navbar-item a {
    text-shadow: 2px 2px 2px #aeaeae;
    text-decoration: none;
    height: 100%;
    width: 100%;
    text-align: center;
    padding: 5px;
    color: #fff;
    /* border: 1px solid #fff; */
    font: var(--font);
    font-size: 20px;
}

.blog-navbar-list :target .blog-navbar-item a,
.blog-navbar-list .blog-navbar-item a:focus,
.blog-navbar-list .blog-navbar-item a:active {
    background-color: #fff;
    color: var(--border-color);
    box-shadow: 3px 3px 3px rgba(0,0,0,0.2);
    box-shadow: 0 0 2px  inset rgba(0, 0, 0, 0.5);
    border-radius: 0 0 5px 5px ;
}
  1. 搜索框设计
  • html
<div class="blog-navbar-search">
    <select style="border:none;outline:medium;" class="blog-navbar-search-select">
        <option>标签</option>
        <option>题目</option>
        <option>作者</option>
    </select>
    <input class="blog-navbar-search-input" style="border:none;outline:medium;" type="text" placeholder="请输入搜索内容">
    <a class="blog-navbar-search-submit" href="#">搜索</a>
</div>
  • css
/* 制作 3D 搜索框 */
.blog-navbar-search {
    position: absolute;
    display: flex;
    height: var(--navbar-item-height);
    width: 270px;
    top: 5px;
    right: 20%;
    border: 1px solid var(--border-color);
    border-radius: calc((var(--navbar-height) - 20px)/2);
    justify-content: center;
    align-items: center;
    row-gap: 10px;
    background-color: #fff;
    box-shadow: 1px 1px #ccc inset, 1px 1px 1px #ccc;
    box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
}

.blog-navbar-search-select {
    border: transparent;
    height: calc(var(--navbar-item-height) - 10px);
    width: 50px;
    color: #666;
    font: var(--font);
    font-weight: normal;
    font-size: 12px;
}

.blog-navbar-search-input {
    border: transparent;
    height: calc(var(--navbar-item-height) - 10px);
    width: 50%;
    color: #666;
    font: var(--font);
    font-weight: normal;
    font-size: 12px;
    margin-left: 15px;
    /* background-color: red; */
    
}   
.blog-navbar-search-submit {
    border: transparent;
    height: calc(var(--navbar-item-height) - 10px);
    width: 50px;
    font: var(--font);
    font-size: 12px;
    font-weight: normal;
    background-color: #fff;
    color: #666;
    text-decoration: none;
    text-align: center;
    margin-top: 3px;
    /* margin-left: 35px; */
}

.blog-navbar-search-submit:active {
    color: #fff;
    text-shadow: rgba(0,0,0,1) 1px 1px 0,
                 rgba(0,0,0,0.8) 2px 2px 0,
                 rgba(0,0,0,0.25) 0 0 5px; 
    text-decoration: none;
}
  1. 列表标签设计
  • html
<div class="article-list-title">
    <div><a href="#">热门</a></div>
    <div><a href="#">最新</a></div>
    <div><a href="#">热议</a></div>
</div>
  • css
.article-list-title {
    display: flex;
    width: 100%;
    height: 50px;
    border-bottom: 1px solid #ccc;
    align-items: center;
}

.article-list-title div {
    height: 20px;
    display: flex;
    align-items: center;
}

.article-list-title div a {
    text-decoration: none;
    font-size: 18px;
    border-right: 1px solid #ccc;
    /* margin: 10px; */
    color: #ccc;
    padding: 0 20px;
}
.article-list-title :target div a,
.article-list-title div a:active,
.article-list-title div a:focus {
    color: var(--border-color);
}
.article-list-title div:nth-last-child(1){
    border: none;
}

布局之后的结果

最终,我并没有真的还原这个html页面,只是参考了这个页面的部分,实现了一个新的html页面。结果如下图所示: