前端开发实战第八天——图文栏目

82 阅读5分钟

1. 开发目标

    图片新闻是门户网站最能吸引用户眼球的内容之一。许多栏目都有大量的图文内容需要展示,比如明星八卦、体育竞技、数码科技等。本文将通过实现一个图片新闻栏目来继续探讨内容布局以及CSS 3的动画效果。

2022-07-22-14-51-26-image.png

    当鼠标悬停在图片上时,图片显示放大的动画。

2. 结构分析

    这是一个处于浏览器水平居中,宽度为960像素的模块,一共包含5篇图文内容。其中第一个图片的大小为480x241像素,其它为238x120像素。大图位于整个模块的左半部,其余4张图片呈田字格显示在模块右侧。每篇文章都有一个叠放在图片上的标题,标题背景为渐变色,增加标题的对比度。

    根据上面的描述,我们用一个模块容器div来实现整体内容宽度和居中。由于图片很明显的分成左右两个部分,最直观的做法是将5篇新闻分成左右两组。为了加深对CSS选择器的理解和使用,我们只用一个包含所有5张图片的无序列表。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片新闻列表</title>
</head>
<body>
    <div class="container">
        <ul class="slide">
            <li class="slide-item">
                <img class="slide-img" src="assets/image/zgnl_1.webp" alt="中国男篮" srcset="">
                <h3 class="slide-title">中国男篮惜败黎巴嫩 无缘亚洲杯4强</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/hhh_2.webp" alt="" srcset="">
                <h3 class="slide-title">“使劲活,好好活”|赵丽颖就是何幸福</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/dyb_3.webp" alt="" srcset="">
                <h3 class="slide-title">东亚杯-全场仅1射门!国足0-3韩国</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/ycl_4.webp" alt="" srcset="">
                <h3 class="slide-title">杨丞琳拍封面大片 造型时髦有个性</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/lss_5.webp" alt="" srcset="">
                <h3 class="slide-title">刘诗诗慵懒悠然风生活照 穿搭时髦气质优雅</h3>
            </li>
        </ul>
    </div>
</body>
</html>

2022-07-22-15-12-20-image.png

3. 样式分析

    根据惯例,我们还是从遵循“先整后零,从上到下,由外而内”的原则。首先设置模块的总宽度,并设置水平居中。同时将bodyulp等元素的内外边距重置为0,去除默认列表样式。

body, ul, p, h3 {
    margin: 0;
    padding: 0;
}

ul {
    list-style: none;
}

.container {
    width: 960px;
    margin: 0 auto;
}

2022-07-23-07-11-24-image.png

    利用浮动属性使列表元素能够水平排列,同时记得利用overflow可以清除浮动对父元素高度的影响。

.slide {
    overflow: hidden;
}

.slide-item {
    float: left;
}

2022-07-23-07-15-58-image.png

    由于图片大小和文字长度问题,单纯运用浮动并不能实现设计图的效果。多个浮动元素的总宽度大于父元素宽度时,会自动换行。每条新闻的图片和文字都处于一个li标签中,我们可以通过设置li标签的尺寸来影响布局。

.slide-item {
    float: left;

    width: 238px;
    height: 120px;
}

.slide-item:first-child {
    width: 480px;
    height: 241px;
}

2022-07-23-07-20-31-image.png

    添加必要的外边距使图片之间适当留白。 这里需要注意两个地方:

  • 图片尺寸大于容器尺寸时,默认会溢出容器边界。可以通过设置img标签大小或者容器的溢出属性(overflow: hidden)避免图片覆盖外边距,从而不显示留白。
  • nth-child伪类根据括号内的数值或计算公式选择子元素。n0开始。因此2n+3表示选择第35个子元素,也就是最右侧显示的图片,不添加右外边距。
img {
    width: 100%;
    height: 100%;
}

.slide-item {
    margin-right: 2px;
    margin-bottom: 1px;

    overflow: hidden;
}

.slide-item:nth-child(2n+3) {
    margin-right: 0;
}

2022-07-23-07-23-50-image.png

    新闻标题需要显示在图片上,发生元素的重叠现象。在HTML中,默认布局会避免内容重叠,一般能够通过两种方式实现元素叠放:

  • 利用负外边距(margin),一般用于两个模块需要发生部分重叠的情况。
  • 运用position属性,同一个容器内的元素进行布局时使用较多。

这里的新闻图片和标题,都位于同一个li标签内,并且标题位置处于整个容器下半部。这种情况下,利用绝对定位(absolute)十分方便。使用绝对定位时,需要注意参照物的选取。

注意:absolute定位的元素,会由内而外地寻找第一个position属性不为static的父元素(祖先),并相对它进行定位。如果没有找到,则相对html标签定位。

.slide-item {
    position: relative;
}

.slide-title {
    position: absolute;
    width: 100%;
    padding-top: 20px;
    padding-left: 12px;

    left: 0;
    bottom: 0;
}

    

    接下来就是设置标题的字体大小、颜色等。最重要的是如何让标题不换行,并且当文字太多时自动用省略号(...)。

.slide-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

2022-07-23-09-00-28-image.png

注意:默认情况下使用padding,元素实际大小为padding+width。因此当width设置为100%时,一定要设置box-sizing: border-box,将padding纳入width中。

    设计图上还有文字大小和渐变的透明背景:

.slide-title {
    color: #fff;
    background-image: linear-gradient(transparent, #000);

    line-height: 50px;
    font-size: 16px;
    font-weight: normal;
}

.slide-item:first-child .slide-title {
    padding-left: 25px;

    font-size: 20px;
}

2022-07-23-09-04-29-image.png

    到目前为止,从表面上看已经实现了设计稿的要求。不过这还只是静态效果,很多时候为了让用户感知到自己的操作,会添加一些具有指示效果的动画。对于图片来说,平缓的大小缩放动画可以做到这一点。CSS 3支持transitiontransformkeyframe等三种动画。

  • transition为元素的状态变化添加过渡动画。
  • transform对元素进行缩放(scale)、平移(translate)、旋转(rotate)等变换。
  • keyframe添加关键帧动画。

    我们希望在鼠标移动到图片上时,图片会有一个平滑放大的效果。结合transformtransition可以轻松实现该动画。

.slide-img {
    transition: all 0.3s;
}

.slide-img:hover {
    transform: scale(1.2);
}

    .slide-img:hover选择鼠标悬停的图片。transform: scale(1.2)表示放大为初始状态的1.2倍,默认围绕元素中心放大。transition使得放大时执行平滑的动画,而不是突变。

4. 完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片新闻列表</title>
    <style>
        ul, p, h3 {
            margin: 0;
            padding: 0;
        }

        ul {
            list-style: none;
        }

        img {
            width: 100%;
        }

        .container {
            width: 960px;
            margin: 0 auto;
        }

        .slide {
            overflow: hidden;
        }

        .slide-item {
            position: relative;
            float: left;

            width: 238px;
            height: 120px;

            margin-right: 2px;
            margin-bottom: 1px;

            overflow: hidden;
        }

        .slide-item:first-child {
            width: 480px;
            height: 241px;
        }

        .slide-item:nth-child(2n+3) {
            margin-right: 0;
        }

        .slide-title {
            position: absolute;
            width: 100%;
            padding-top: 20px;
            padding-left: 12px;

            left: 0;
            bottom: 0;

            color: #fff;
            background-image: linear-gradient(transparent, #000);

            line-height: 50px;
            font-size: 16px;
            font-weight: normal;

            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;

            box-sizing: border-box;
        }

        .slide-item:first-child .slide-title {
            padding-left: 25px;

            font-size: 20px;
        }

        .slide-img {
            transition: all 0.3s;
        }

        .slide-img:hover {
            transform: scale(1.2);
        }
    </style>
</head>
<body>
    <div class="container">
        <ul class="slide">
            <li class="slide-item">
                <img class="slide-img" src="assets/image/zgnl_1.webp" alt="中国男篮" srcset="">
                <h3 class="slide-title">中国男篮惜败黎巴嫩 无缘亚洲杯4强</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/hhh_2.webp" alt="" srcset="">
                <h3 class="slide-title">“使劲活,好好活”|赵丽颖就是何幸福</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/dyb_3.webp" alt="" srcset="">
                <h3 class="slide-title">东亚杯-全场仅1射门!国足0-3韩国</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/ycl_4.webp" alt="" srcset="">
                <h3 class="slide-title">杨丞琳拍封面大片 造型时髦有个性</h3>
            </li>
            <li class="slide-item">
                <img class="slide-img" src="assets/image/lss_5.webp" alt="" srcset="">
                <h3 class="slide-title">刘诗诗慵懒悠然风生活照 穿搭时髦气质优雅</h3>
            </li>
        </ul>
    </div>
</body>
</html>

5. 待解问题

  • nth-child伪类选择器
  • CSS 3动画
  • position详解
  • 文本属性