一、项目规划

1、开发工具以及技术栈

开发工具:VScode、Photoshop、Chrome浏览器
技术栈: HTML5 + CSS3 + JS

2、搭建前言

1)创建文件夹

一般来说,项目文件夹创建如下:
(我没有全部按照此方法创建,因为只做了首页)
项目文件夹创建

2)字体图标使用

字体文件我用了icomoon字库
使用简述:
1、下载:选中要使用的图标——>generate font ——>download
2、引入:压缩包解压后里面的fonts文件复制放入页面根目录下——> 复制解压后文件夹中style.css文件中的一部分代码到common.css中

//例:style.css文件中的一部分代码
@font-face {
            font-family: 'icomoon';
            src: url('fonts/icomoon.eot?um2um6');
            src: url('fonts/icomoon.eot?um2um6#iefix') format('embedded-opentype'), url('fonts/icomoon.ttf?um2um6') format('truetype'), url('fonts/icomoon.woff?um2um6') format('woff'), url('fonts/icomoon.svg?um2um6#icomoon') format('svg');
            font-weight: normal;
            font-style: normal;
            font-display: block;
        }

有两种引用方式:
① 在span标签内放入复制的口 ——> 给span声明font-family: ‘icomoon’;
②在需要放入字体图标的标签内进行如下声明:

.topbar_car::before {
            content: '\e93a';
            font-family: 'icomoon';
        }

3、追加:import icons ——> 选择selection.json ——> 选中要使用的图标——>generate font ——>download

3)网站TDK三大标签SEO优化

  SEO(Search Engine Optimization)汉译为搜索引擎优化,是一种利用搜索引擎的规则提高网站在有关搜索引擎内自然排名的方式。
  SEO 的目的是对网站进行深度的优化,从而帮助网站获取免费的流量,进而在搜索引擎上提升网站的排名,提高网站的知名度。页面必须有三个标签用来符合SEO 优化。

① title 网站标题
 title 具有不可替代性,是我们内页的第一个重要标签,是搜索引擎了解网页的入口和对网页主题归属的最佳判断点。
 建议:网站名(产品名)-网站的介绍(尽量不要超过30个汉字)

②description 网站说明
简要说明我们网站主要是做什么的。
例如:

<meta name="description" content="京东JD.COM-专业的综合网上购物商城,销售家电、数码通讯、电脑、家居百货、服装服饰、母婴、图书、食品等数万个品牌优质商品.便捷、诚信的服务,为您提供愉悦的网上购物体验!" />

③keywords 关键字
keywords 是页面关键词,是搜索引擎的关注点之一。
 keywords 最好限制为6~8 个关键词,关键词之间用英文逗号隔开,采用关键词1,关键词2 的形式。
例如:

<meta name= " keywords" content="网上购物,网上商城,手机,笔记本,脑,MP3,CD,VCD,DV,相机,数码,配件,手表,存储卡,京东" />
4)LOGO SEO 优化

1、logo 里面首先放一个h1标签,目的是为了提权,告诉搜索引擎,这个地方很重要。
2、h1 里面再放一个链接,可以返回首页的,把logo 的背景图片给链接即可。
3、为了搜索引擎收录我们,我们链接里面要放文字(网站名称),但是文字不要显示出来。
 方法1:text-indent 移到盒子外面(text-indent: -9999px) ,然后overflow:hidden,
淘宝的做法。
 方法2:直接给font-size: 0;就看不到文字了,京东的做法。
4、最后给链接一个title属性,这样鼠标放到logo 上就可以看到提示文字了。
例:

<div class="header_logo">
     <h1>
         <a href="index.html" title="小米商城">小米商城</a>
     </h1>
</div>

在这里插入图片描述

二、具体实现

整体布局:
小米首页盒子摆放

1、头部

思维导图:
在这里插入图片描述

1)头部顶栏site_topbar制作

在这里插入图片描述

①给site_topbar这个大盒子一个高,里面的子盒子会继承该行高,里面包含版心的盒子;
②版心盒子里面包含1号盒子左浮动
③版心盒子里面包含2号盒子定位
④版心盒子里面包含3号盒子定位
⑤需要用到字体图标


问题1:
浏览器缩放时,背景色显示不全,如下:
在这里插入图片描述
解决:
给site_topbar加上min-width: 1263.33px;
(原来没有给宽度)
问题2:
浏览器缩放时,布局变乱
解决:
在html布局时需要把内容放在版心w的盒子里,而不是直接引用类w,且在写css时
在这里插入图片描述

2)头部site_header制作

在这里插入图片描述

2、主要部分

思维导图:
在这里插入图片描述

1)菜单menu制作

在这里插入图片描述
①这里用绝对定位来做,并且一定要给z-index: 2;让菜单压住轮播图在其上面;
②每个后面的>用after伪元素做并且用了字体图标;

.menu ul li a::after {
            position: absolute;
            right: 30px;
            content: '\e906';
            font-family: 'icomoon';
            font-size: 22px;
        }
2)轮播图.focus制作

在这里插入图片描述

<div class="focus">
   <!-- 左侧侧按钮 -->
   <a href="javascript:;" class="arrow-l"></a>
   <!-- 右侧按钮 -->
   <a href="javascript:;" class="arrow-r"></a>
   <!-- 核心的滚动区域 -->
   <ul>
      <li>
         <a href="javascrip:;"><img src="images/banner.jpg" alt=""></a>
      </li>
      <li>
         <a href="javascrip:;"><img src="images/banner1.jpg" alt=""></a>
      </li>
      <li>
          <a href="javascrip:;"><img src="images/banner2.jpg" alt=""></a>
       </li>
       <li>
          <a href="javascrip:;"><img src="images/banner3.jpg" alt=""></a>
       </li>
   </ul>
   <!-- 小圆圈 -->
   <ol class="circle">
   </ol>
   </div>

①轮播图是用ul>li*4,然后给li浮动,注意!!!ul一定要给够宽,要不然图片不会显示在一排;
②1号盒子focus设置和图片一样的宽和高,然后写js实现左右箭头和小圆圈结合图片播放的功能,实现功能以后给focus一个overflow: hidden;超出大盒子的图片就会被隐藏;

 .focus {
            position: relative;
            width: 1226px;
            height: 460px;
            overflow: hidden;
        }
.focus ul {
            position: absolute;
            top: 0;
            left: 0;
            width: 600%;
        }

③2号和3号盒子用绝对定位,且用了字体图标;

.arrow-l,
.arrow-r {
    position: absolute;
    top: 50%;
    width: 41px;
    height: 69px;
    color: #e1dddd;
    font-family: 'icomoon';
    font-size: 45px;
    z-index: 2;
        }

④4号盒子是利用JS根据ul有几张图片来动态生成小圆圈的,在这之前需要先确定好小圆圈在css中的样式;

.circle li {
     float: left;
     margin: 0 3px;
     width: 12px;
     height: 12px;
     border: 3px solid rgba(105, 101, 101, .6);
     border-radius: 50%;
 }
 .current {
     background: #666;
 }

⑤提前封装好了一个animate函数放在animate.js中,在index.js中可直接调用animate函数,不过要记得在index.html中引入这两个js;

function animate(obj, target, callback) {
    //callback = function() {}  调用的时候 callback(),定时器停止时调用
    clearInterval(obj.timer);
    //解决连续点击,图片播放速度变快的问题
    obj.timer = setInterval(function() {
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            callback && callback();
            // if (callback) {
            //     // 调用函数
            //     callback();
            // }
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15)
}

⑥轮播图js实现

// 1.获取元素
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    var focusWidth = focus.offsetWidth;

    // 2.动态生成小圈圈
    var ul = focus.querySelector('ul');
    var ol = focus.querySelector('.circle');

    for (var i = 0; i < ul.children.length; i++) {
        // 创建一个小li
        var li = document.createElement('li');
        // 记录当前小圆圈的索引号 通过自定义属性来做
        li.setAttribute('index', i);
        // 把小li插入到ol 里面
        ol.appendChild(li);
        // 3. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
        li.addEventListener('click', function() {
            // 干掉所有人
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 留下我自己
            this.className = 'current';
            // 4. 点击小圆圈,移动图片 当然移动的是 ul
            // ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
            // 当我们点击了某个小li 就拿到当前小li 的索引号
            var index = this.getAttribute('index');

            animate(ul, -index * focusWidth);
        });
    }
    ol.children[0].className = 'current';
    // 5. 克隆第一张图片(li,加true深复制 复制里面的子节点)放到ul 最后面
    var first = ul.children[0].cloneNode(true);
    ul.appendChild(first);
    // 6. 点击右侧按钮, 图片滚动一张
    var num = 0;
    // circle 控制小圆圈的播放,与左右侧按钮联系起来
    var circle = 0;
    // flag 节流阀
    var flag = true;
    arrow_r.addEventListener('click', function() {
        if (flag) {
            flag = false; // 关闭节流阀
            // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function() {
                flag = true; //打开节流阀
            });
            // 7. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈
            circle++;
            // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原
            if (circle == ol.children.length) {
                circle = 0;
            }
            // 调用函数
            circleChange();
        }
    });
    // 8. 左侧按钮做法
    arrow_l.addEventListener('click', function() {
        if (flag) {
            flag = false; // 关闭节流阀
            // 如果走到了第一张图片,快速到第四张图片
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';
            }
            num--;
            animate(ul, -num * focusWidth, function() {
                flag = true; //打开节流阀
            });
            // 7. 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈
            circle--;
            // 如果circle <0说明第一张图片,则小圈圈要改为第四个小圈圈
            // if (circle < 0) {
            //     circle = ol.children.length - 1;
            // }
            circle = circle < 0 ? ol.children.length - 1 : circle;
            // 调用函数
            circleChange();
        }
    });

    function circleChange() {
        // 先清除其余小圆圈的current类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 留下当前的小圆圈的current类名
        ol.children[circle].className = 'current';
    }
    // 10.自动播放轮播图
    var timer = setInterval(function() {
        // 手动调用点击事件
        arrow_r.click();
    }, 5000);
    // 11.鼠标经过focus自动播放停止
    focus.addEventListener('mouseenter', function() {
        clearInterval(timer);
        timer = null; // 清除定时器变量
    });
    //鼠标离开focus继续自动播放
    focus.addEventListener('mouseleave', function() {
        timer = setInterval(function() {
            // 手动调用点击事件
            arrow_r.click();
        }, 5000);

3、推荐部分

思维导图:
在这里插入图片描述

在这里插入图片描述

① 给recommend大盒子一个高和margin-top调好位置以后,进行大盒子里面的布局;
②1号盒子左浮,设置高和宽,里面的6个li也给个浮动并且设置合适的高和宽,li在1号盒子里面自动排号位置;
③ 2号盒子左浮;

4、内容产品部分

思维导图:
在这里插入图片描述

1)手机模块

在这里插入图片描述
①注意!container大盒子不要给高度,里面的产品内容可以即时添加,这里只详细说明手机模块,写的时候注意样式复用性,其他产品模块和手机模块类似,结构可使用手机模块的,但是注意修改细节;
②banner盒子里直接放图片就行了;
②1号盒子box_hd给高和宽,h2标签里放手机并且左浮;
③2号盒子more右浮,后面用字体图标;
④3号盒子给宽和高;
⑤4号盒子给宽和高左浮;
⑥5号盒子给宽和高左浮,里面的li给合适的高和宽浮动排好位置,然后在li里面进行布局;如下:

<li class="brick_item">
   <a href="#">
     <div class="figure_img"><img src="images/phone_r1.webp" alt=""></div>
     <h3>Redmi K50 Pro</h3>
     <p class="desc">2k直屏的狠旗舰</p>
     <p class="price">2999元起</p>
   </a>
</li>
2)手表模块

在这里插入图片描述
①手表模块1号盒子more与手机模块里的more盒子里面的结构不一样,如下对比:

//手机模块里的more盒子
<div class="more"><a href="#">查看更多<i></i></a></div>
//手表模块的more盒子
<div class="more">
   <ul>
      <li>热门</li>
      <li>穿戴</li>
    </ul>
</div>

②2号盒子是每个产品模块r盒子里的最后一个li,给这个li写一个类名,在里面放两个盒子,盒子的样式需要另写,注意权重需要足够大,能覆盖之前写给li的样式,如下:

<li class="final">
    <div class="moiety brick_item">
        <img src="images/watches_r1.webp" alt="">
        <h3>Redmi Buds 3 青春版</h3>
        <p class="price">99元</p>
    </div>
    <div class="bmore brick_item">
       <div class="bmore_l">
          浏览更多
          <small>热门</small>
       </div>
       <div class="bmore_r"></div>
    </div>
</li>
3)家电模块

在这里插入图片描述
①这里共挑出3个产品内容模块的示例——展示小米产品内容模块不同的地方;
②1号盒子是l盒子里面放两个li,li的结构样式可直接用r盒子里li的;
如下:

//手表模块的l盒子
<div class="l">
    <ul>
       <li class="brick_item">
          <a href="#"><img src="images/watches_r.webp" alt=""></a>
       </li>
   </ul>
</div>
//家电模块的l盒子
<div class="l">
  <ul>
     <li class="sep_ab brick_item">
        <a href="#">
          <div class="figure_img">
             <img src="images/electric_r.webp" alt="">       
          </div> 
          <h3>Redmi K50 Pro</h3>
          <p class="desc">2k直屏的狠旗舰</p>
          <p class="price">2999元起</p>
        </a>
     </li>
     <li class="sep_be brick_item">
       <a href="#">
         <div class="figure_img">
            <img src="images/electric_r1.webp" alt="">
         </div>
         <h3>Redmi K50 Pro</h3>
         <p class="desc">2k直屏的狠旗舰</p>
         <p class="price">2999元起</p>
       </a>
     </li>
   </ul>
</div>

③2号盒子可采用直接将手表模块最后一个li的第一个盒子删除的结构;

4)视频模块

在这里插入图片描述

①在box_bd大盒子里放4个li浮动,每个li分两部分1和3写;
②在第1部分放个盒子,盒子里放张图片和span标签(写一个圆角长方形,用绝对定位固定在盒子里);
③在span标签里放个i标签用字体图标实现第2部分里的三角形;

结构如下:

<li class="brick_item">
   <a href="#">
      <div class="figure_img">
          <img src="images/vedio.webp" alt="">
          <span class="play">
               <i class="icommon_play"></i>
          </span>
      </div>
      <h3 class="title">2021年春季新品发布会第一场</h3>
      <p class="desc"></p>
    </a>
</li>

样式如下:
(这里重点给了span标签及其里面的样式)

/* 视频模块的小正方形 */
 
 .vedio .box_bd .play {
     z-index: 2;
     position: absolute;
     left: 20px;
     bottom: 10px;
     width: 32px;
     height: 20px;
     border: 2px solid #fff;
     border-radius: 12px;
     background-color: rgba(0, 0, 0, .6);
     color: #fff;
     text-align: center;
 }
 
 .vedio .box_bd .play .icommon_play {
     font-family: 'icomoon';
     line-height: 16px;
     font-size: 16px;
 }

5)另外:以上产品内容的每个li在鼠标经过时会有一个阴影加上移的效果,我是专门给这个效果写了一个.brick_item样式,然后把这个类名写进每一个需要这个效果的li里面;
样式如下:

.brick_item {
     transition: all .2s linear;
 }
 
 .brick_item:hover {
     box-shadow: 0 15px 30px rgba(0 0 0 /10%);
     transform: translate3d(0, -2px, 0);
 }

补充:使用css3阴影box-shadow和2D转换transform不会影响其他元素的位置。

5、底部

思维导图:
在这里插入图片描述

1)site_footer部分

在这里插入图片描述
①1号盒子footer_service给5个li浮动,用before伪元素写前面的图标;
注意:1号大盒子没有给高,给里面的li写宽和高,这样给一个边框的时候就可以实现如上效果。
②2号盒子一样没有给高,让里面的内容撑开盒子;
③3号盒子左浮也都没有给高;
④4号盒子右浮,人工客服前用before伪元素写字体图标,关注小米后的wb和wx用图片来展示,鼠标经过wb和wx分别会有一个变色的效果(这里是有两张图片,变色前一张图片,鼠标经过实现链接换成变色后图片的)
⑤鼠标经过wx,wx会变色的同时会出现一张二维码,该二维码用绝对定位写好位置后隐藏,鼠标经过显示。

2)site_info部分

在这里插入图片描述
①1号盒子用子绝父相,父盒子是site_info大盒子;
②2号盒子用3个p标签实现;
③3号盒子用4个a标签里放ing浮动实现;
④4号盒子水平居中。

6、侧边固定栏

思维导图:
在这里插入图片描述

1)滚动至内容产品之前的侧边栏

在这里插入图片描述
这里为了更好的展示,我直接将鼠标经过才会显示的内容直接显示出来;

①home_tool_bar大盒子用固定定位放好位置;
②在home_tool_bar大盒子里写6个a标签,让a标签变成块级元素给高和宽,a标签里放i标签(用字体图标)和span标签(放鼠标经过会显示的文本内容);如下:

<a href="#" class="item">
   <i></i>
    <span class="text">个人中心</span>
</a>

③最后一个a标签backtop比较特殊,给一个margin-top: 14px;可实现他与上面5个标签的距离;
④鼠标经过后会出现的内容用子绝父相实现,父盒子是每个内容各自的a.item标签;(一定要记得给z-index使鼠标经过出现的内容压在所有内容上面)

/* 经过固定侧边栏出现的盒子 */
 /* 共同样式 */
 
 .home_tool_bar .item .pop_content,
 .home_tool_bar .item .text {
     z-index: 22;
     display: none;
     position: absolute;
     right: 38px;
     background: #fff;
     border: 1px solid #f5f5f5;
 }
 
 /* 二维码盒子 */
 .home_tool_bar .item .pop_content {
     top: 0;
     padding: 14px;
 }
 .home_tool_bar .item .pop_content .desc {
     display: block;
     width: 82px;
     margin: 14px auto 0;
     color: #757575;
     font-size: 14px;
 }
 
 /* 内容盒子 */
 .home_tool_bar .item .text {
     top: 10%;   /* 相对于.item位置的10% ,是鼠标出现的内容相对与a.item垂直居中*/
     padding: 0 8px;
     height: 28px;
     line-height: 28px;
     color: #757575;
     font-size: 14px;
     white-space: nowrap;/* 强制一行显示  */
 }

⑤每个鼠标经过出现的盒子之前有个小三角形,用before伪元素和子绝父相实现,父盒子是鼠标经过出现的盒子;(注意!小三角在二维码和内容的地方不一致)

/* 三角形 */
.home_tool_bar .item .text::before,
 .home_tool_bar .item .pop_content::before {
     z-index: 23;
     position: absolute;
     top: 15px;
     right: -13px;
     content: "";
     width: 0;
     height: 0;
     border: 6px solid transparent;
     border-left-color: #fff;
 }
 
 .home_tool_bar .item .text::before {
     top: 30%;
 }

⑥调整好各种样式后隐藏鼠标经过后才会出现的盒子以及滚动至产品内容才会出现的回到顶部backtop;

2)滚动至内容产品之后的侧边栏

在这里插入图片描述
用js实现滚动至内容产品部分出现回到顶部backtop

// 二、固定栏
    // 获取元素
    var container = document.querySelector('.container');
    var backtop = document.querySelector('.backtop');
    // 获得内容产品模块的位置
    var containerTop = container.offsetTop;

    document.addEventListener('scroll', function() {
        // 页面被卷进去的头部的距离大于等于内容产品模块的位置时,返回顶部就出现
        if (window.pageYOffset >= containerTop) {
            backtop.style.display = 'block';
        } else {
            backtop.style.display = 'none';
        }
    })

补充:页面被卷去的头部值可以通过window.pageYOffset获得,注意!元素被卷去的头部是element.scrollTop。

以上是我的薄见,仍有许多待改进的地方,后面会陆续更新改进,欢迎各位大佬指出我不足或者不对的地方(●’◡’●)*

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐