普通视图

发现新文章,点击刷新页面。
昨天以前首页

超实用!HTML&CSS&JS 下拉多选功能解析,建议收藏

作者 前端Hardy
2025年1月16日 15:30

在前端开发过程中,我们常常会遇到一些看似常规却又充满挑战的需求。最近我就接到了一个任务,要求在页面中实现一个下拉选择支持多选的功能。起初,我考虑使用原生的 select 标签,但在实际操作中发现其默认的 UI 无法满足项目的设计需求,因此决定使用原生 JavaScript 来打造这个功能。以下是我整个开发过程的详细记录。

一、需求分析

项目需要一个能够让用户从多个选项中选择多个变量的下拉菜单。用户选择的变量需要实时显示在输入框中,并且在页面刷新后,用户之前的选择能够被保留。这意味着我们不仅要实现多选的交互逻辑,还要处理数据的存储和读取。

二、HTML 结构搭建

首先,我创建了一个基本的 HTML 结构。使用一个 div 容器作为整个下拉选择组件的外壳,并赋予其 container 类,用于设置样式和布局。在容器内部,有一个标题 h1 用于描述该组件的功能。 接着,创建了一个 select-container 类的 div 作为下拉选择的容器。在这个容器中,select-input 类的 div 用于显示当前选择的变量或提示信息,并且包含一个 input 元素用于显示内容,以及一个 span 元素用于显示下拉箭头。select-options 类的 div 则用于存放所有的可选变量,初始状态下是隐藏的。

<div class="container">
    <h1>下拉选择支持多选</h1>
    <div class="select-container">
      <div class="select-input">
        <input type="text" id="selectedVariablesInput" placeholder="请选择变量" readonly>
        <span class="select-arrow"></span>
      </div>
      <div class="select-options">
      </div>
    </div>
</div>

三、CSS 样式设计

为了让组件看起来美观且易于使用,我使用 CSS 进行了样式设计。设置了页面的整体背景颜色、字体等基本样式。对于 container 类,设置了最大宽度、高度、边距、内边距、背景颜色、阴影和圆角,使其在页面中居中显示且具有立体感。 对于 select-input,设置了其显示为弹性布局,设置了边框、圆角、内边距和背景颜色,使其看起来像一个输入框。其中的 input 元素去除了默认边框和轮廓,设置了内边距、字体大小和颜色,使其与外层 div 融合且文字清晰可读。select-arrow 则通过设置三角形的样式来模拟下拉箭头。 select-options 在默认状态下是隐藏的,通过设置 opacity 和 transform 属性实现了显示和隐藏的动画效果。同时,设置了其最大高度、溢出属性、边框、圆角、阴影等,使其在显示时具有良好的视觉效果。每个选项 label 设置了内边距、高度、行高和颜色,并且在鼠标悬停时改变背景颜色以提供交互反馈。

    body {
      font-family: Arial, sans-serif;
      background-color#f5f5f5;
      margin0;
      padding0;
    }

    .container {
      max-width300px;
      height400px;
      margin0 auto;
      padding20px;
      background-color#fff;
      box-shadow0 0 10px rgba(0000.1);
      border-radius5px;
      margin-top50px;
    }

    h1 {
      text-align: center;
      color#333;
      font-size24px;
    }

    .select-container {
      position: relative;
    }

    .select-input {
      display: flex;
      align-items: center;
      border1px solid #e4e7ed;
      border-radius4px;
      padding0 10px;
      cursor: pointer;
      background-color#fff;
    }

    .select-input input {
      flex1;
      border: none;
      outline: none;
      padding10px 0;
      font-size14px;
      cursor: pointer;
      color#555;
    }

    .select-arrow {
      width0;
      height0;
      border-left5px solid transparent;
      border-right5px solid transparent;
      border-top5px solid #c0c4cc;
      margin-left10px;
    }

    .select-options {
      position: absolute;
      topcalc(100% + 10px);
      left0;
      width100%;
      background-color#fff;
      z-index1000;
      max-height200px;
      overflow-y: auto;
      display: none;
      opacity0;
      transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
      transformtranslateY(10px);
      border1px solid #e4e7ed;
      border-radius4px;
      box-shadow0 2px 12px 0 rgba(000, .1);
      box-sizing: border-box;
      margin5px 0;
      padding10px 0;
      scrollbar-width: none;
      -ms-overflow-style: none;
    }

    .select-options::-webkit-scrollbar {
      width0;
      height0;
    }

    .select-options.show {
      display: block;
      opacity1;
      transformtranslateY(0);
    }

    .select-options label {
      display: flex;
      align-items: center;
      padding0 20px;
      cursor: pointer;
      height34px;
      line-height34px;
      color#555;
    }

    .select-options label:hover {
      background-color#f5f7fa;
    }

    .select-options input[type="checkbox"] {
      margin-right10px;
    }

    .selected-variable {
      color#409eff !important;
    }

四、JavaScript 交互逻辑实现

1、生成选项列表: 使用 JavaScript 动态生成了 100 个变量选项。通过 Array.from 方法创建一个包含 100 个元素的数组,每个元素代表一个变量。然后遍历这个数组,为每个变量创建一个 label 元素和一个 input 元素(类型为 checkbox),将它们添加到 select-options 容器中。

const variables = Array.from({ length: 100 }, (_, i) => `变量 ${i + 1}`);
const selectOptions = document.querySelector('.select - options');
variables.forEach(variable => {
    const label = document.createElement('label');
    const input = document.createElement('input');
    input.type = 'checkbox';
    input.value = variable;
    input.classList.add('variable - checkbox');
    label.appendChild(input);
    label.appendChild(document.createTextNode(variable));
    selectOptions.appendChild(label);
});

2、读取和回显选择状态: 从本地缓存 localStorage 中读取之前保存的选择状态。如果存在保存的变量,遍历所有的复选框,将已选中的变量对应的复选框设置为 checked 状态,并为其 label 添加 selected-variable 类,以显示选中的样式。同时,调用 updateSelectedVariablesInput 函数更新输入框的内容。

const savedVariables = JSON.parse(localStorage.getItem('selectedVariables')) || [];
selectOptions.querySelectorAll('.variable - checkbox').forEach(input => {
    if (savedVariables.includes(input.value)) {
        input.checked = true;
        input.parentNode.classList.add('selected - variable');
    }
});
updateSelectedVariablesInput();

3、更新输入框内容: 定义了 updateSelectedVariablesInput 函数,该函数获取所有被选中的变量的值,并将它们以逗号分隔的形式显示在输入框中。如果没有选中任何变量,则显示提示信息。同时,将当前的选择状态保存到本地缓存 localStorage 中。

function updateSelectedVariablesInput() {
    const selectedVariables = Array.from(selectOptions.querySelectorAll('.variable - checkbox:checked'))
     .map(input => input.value);
    selectedVariablesInput.value = selectedVariables.join(', ') || '请选择变量';
    localStorage.setItem('selectedVariables', JSON.stringify(selectedVariables));
}

4、切换选项列表显示状态: 为 select-input 添加点击事件监听器。当点击 select-input 时,如果选项列表当前是显示状态,则隐藏它;如果是隐藏状态,则显示它。

const selectInput = document.querySelector('.select-input');
selectInput.addEventListener('click'function () {
    if (selectOptions.classList.contains('show')) {
        selectOptions.classList.remove('show');
    } else {
        selectOptions.classList.add('show');
    }
});

5、隐藏选项列表: 为整个文档添加点击事件监听器。当点击页面上除了 select - input 和 select - options 之外的其他地方时,隐藏选项列表。

document.addEventListener('click', function (event) {
    if (!selectInput.contains(event.target) &&!selectOptions.contains(event.target)) {
        selectOptions.classList.remove('show');
    }
});

6、监听复选框变化: 为 select - options 添加 change 事件监听器。当复选框的状态发生改变时,根据其是否被选中,为对应的 label 添加或移除 selected - variable 类,并调用 updateSelectedVariablesInput 函数更新输入框内容和本地缓存。

selectOptions.addEventListener('change', function (event) {
    if (event.target.type === 'checkbox') {
        const label = event.target.parentNode;
        if (event.target.checked) {
            label.classList.add('selected-variable');
        } else {
            label.classList.remove('selected-variable');
        }
        updateSelectedVariablesInput();
    }
});

五、总结

起初,面对下拉多选功能的需求,或许大家和我一样,第一反应是依赖现成的 UI 框架。但当我决定尝试用原生 JavaScript 去实现时,才真正打开了前端开发的新世界大门。对于刚入门的前端小白来说,不要害怕尝试原生开发,这能极大地提升我们对前端技术的掌握程度。遇到问题时,多查阅资料,不断调试,每一次解决问题都是一次成长。相信大家在未来的项目中,只要积累足够的经验,都能高效、出色地完成任务,创造出优秀的前端应用。

源代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>下拉选择支持多选</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      background-color#f5f5f5;
      margin0;
      padding0;
    }

    .container {
      max-width300px;
      height400px;
      margin0 auto;
      padding20px;
      background-color#fff;
      box-shadow0 0 10px rgba(0000.1);
      border-radius5px;
      margin-top50px;
    }

    h1 {
      text-align: center;
      color#333;
      font-size24px;
    }

    .select-container {
      position: relative;
    }

    .select-input {
      display: flex;
      align-items: center;
      border1px solid #e4e7ed;
      border-radius4px;
      padding0 10px;
      cursor: pointer;
      background-color#fff;
    }

    .select-input input {
      flex1;
      border: none;
      outline: none;
      padding10px 0;
      font-size14px;
      cursor: pointer;
      color#555;
    }

    .select-arrow {
      width0;
      height0;
      border-left5px solid transparent;
      border-right5px solid transparent;
      border-top5px solid #c0c4cc;
      margin-left10px;
    }

    .select-options {
      position: absolute;
      topcalc(100% + 10px);
      left0;
      width100%;
      background-color#fff;
      z-index1000;
      max-height200px;
      overflow-y: auto;
      display: none;
      opacity0;
      transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
      transformtranslateY(10px);
      border1px solid #e4e7ed;
      border-radius4px;
      box-shadow0 2px 12px 0 rgba(000, .1);
      box-sizing: border-box;
      margin5px 0;
      padding10px 0;
      scrollbar-width: none;
      -ms-overflow-style: none;
    }

    .select-options::-webkit-scrollbar {
      width0;
      height0;
    }

    .select-options.show {
      display: block;
      opacity1;
      transformtranslateY(0);
    }

    .select-options label {
      display: flex;
      align-items: center;
      padding0 20px;
      cursor: pointer;
      height34px;
      line-height34px;
      color#555;
    }

    .select-options label:hover {
      background-color#f5f7fa;
    }

    .select-options input[type="checkbox"] {
      margin-right10px;
    }

    .selected-variable {
      color#409eff !important;
    }
  </style>
</head>

<body>
  <div class="container">
    <h1>下拉选择支持多选</h1>
    <div class="select-container">
      <div class="select-input">
        <input type="text" id="selectedVariablesInput" placeholder="请选择变量" readonly>
        <span class="select-arrow"></span>
      </div>
      <div class="select-options">
      </div>
    </div>
  </div>
  <script>
    document.addEventListener('DOMContentLoaded'function () {
      const variables = Array.from({ length100 }, (_, i) => `变量 ${i + 1}`);
      const selectInput = document.querySelector('.select-input');
      const selectedVariablesInput = document.getElementById('selectedVariablesInput');
      const selectOptions = document.querySelector('.select-options');

      // 动态生成变量选择列表
      variables.forEach(variable => {
        const label = document.createElement('label');
        const input = document.createElement('input');
        input.type = 'checkbox';
        input.value = variable;
        input.classList.add('variable-checkbox');
        label.appendChild(input);
        label.appendChild(document.createTextNode(variable));
        selectOptions.appendChild(label);
      });

      // 从本地缓存中读取之前保存的选择状态并回显到输入框
      const savedVariables = JSON.parse(localStorage.getItem('selectedVariables')) || [];
      selectOptions.querySelectorAll('.variable-checkbox').forEach(input => {
        if (savedVariables.includes(input.value)) {
          input.checked = true;
          input.parentNode.classList.add('selected-variable');
        }
      });
      updateSelectedVariablesInput();

      // 更新输入框内容的函数
      function updateSelectedVariablesInput() {
        const selectedVariables = Array.from(selectOptions.querySelectorAll('.variable-checkbox:checked'))
          .map(input => input.value);
        selectedVariablesInput.value = selectedVariables.join(', ') || '请选择变量';
        // 直接存储选择到本地缓存
        localStorage.setItem('selectedVariables'JSON.stringify(selectedVariables));
      }

      // 点击输入框切换选项列表的显示状态
      selectInput.addEventListener('click'function () {
        if (selectOptions.classList.contains('show')) {
          selectOptions.classList.remove('show');
        } else {
          selectOptions.classList.add('show');
        }
      });

      // 点击页面其他地方隐藏选项列表
      document.addEventListener('click'function (event) {
        if (!selectInput.contains(event.target) && !selectOptions.contains(event.target)) {
          selectOptions.classList.remove('show');
        }
      });

      // 监听复选框的变化并更新输入框内容及本地缓存
      selectOptions.addEventListener('change'function (event) {
        if (event.target.type === 'checkbox') {
          const label = event.target.parentNode;
          if (event.target.checked) {
            label.classList.add('selected-variable');
          } else {
            label.classList.remove('selected-variable');
          }
          updateSelectedVariablesInput();
        }
      });
    });
  </script>
</body>

</html>

HTML&CSS:2025新年日历卡片

作者 前端Hardy
2025年1月16日 11:55

这段代码创建了一个具有 3D 效果和动态背景的日历卡片,通过 CSS 技术实现了卡片的背景移动、3D 旋转和内容的 3D 位置变化效果,为页面添加了视觉吸引力和用户交互体验。

演示效果

HTML&CSS

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>公众号关注:前端Hardy</title>
    <style>
        body {
            margin0;
            padding0;
            background#212121;
            display: flex;
            align-items: center;
            justify-content: center;
            height100vh;
        }

        .parent {
            height200px;
            width300px;
            padding20px;
            perspective1000px;
        }

        .card {
            padding-top50px;
            border3px solid rgb(255255255);
            transform-style: preserve-3d;
            backgroundlinear-gradient(135deg#0000 18.75%#f3f3f3 0 31.25%#0000 0),
                repeating-linear-gradient(45deg#f3f3f3 -6.25% 6.25%#ffffff 0 18.75%);
            background-size60px 60px;
            background-position0 00 0;
            background-color#f0f0f0;
            width100%;
            box-shadowrgba(1421421420.30px 30px 30px -10px;
            transition: all 0.5s ease-in-out;
        }

        .card:hover {
            background-position: -100px 100px, -100px 100px;
            transformrotate3d(0.50.5010deg);
        }

        .content-box {
            backgroundrgba(41932500.732);
            transition: all 0.5s ease-in-out;
            padding60px 25px 25px 25px;
            transform-style: preserve-3d;
        }

        .content-box .card-title {
            display: inline-block;
            color: white;
            font-size25px;
            font-weight900;
            transition: all 0.5s ease-in-out;
            transformtranslate3d(0px0px50px);
        }

        .content-box .card-title .subtitle {
            display: inline-block;
            color: white;
            font-size16px;
            font-weight900;
            transition: all 0.5s ease-in-out;
            transformtranslate3d(0px0px50px);
        }

        .content-box .card-title:hover {
            transformtranslate3d(0px0px60px);
        }

        .content-box .card-content {
            margin-top10px;
            font-size12px;
            font-weight700;
            color#f2f2f2;
            transition: all 0.5s ease-in-out;
            transformtranslate3d(0px0px30px);
        }

        .content-box .card-content:hover {
            transformtranslate3d(0px0px60px);
        }

        .content-box .see-more {
            cursor: pointer;
            margin-top1rem;
            display: inline-block;
            font-weight900;
            font-size9px;
            text-transform: uppercase;
            colorrgb(7185255);
            background: white;
            padding0.5rem 0.7rem;
            transition: all 0.5s ease-in-out;
            transformtranslate3d(0px0px20px);
        }

        .content-box .see-more:hover {
            transformtranslate3d(0px0px60px);
        }

        .date-box {
            position: absolute;
            top30px;
            right30px;
            height50px;
            width50px;
            background: white;
            border1px solid rgb(7185255);
            padding10px;
            transformtranslate3d(0px0px80px);
            box-shadowrgba(1001001110.20px 17px 10px -10px;
        }

        .date-box span {
            display: block;
            text-align: center;
        }

        .date-box .month {
            colorrgb(4193250);
            font-size11px;
            font-weight700;
            margin-bottom5px;
        }

        .date-box .date {
            font-size20px;
            font-weight900;
            colorrgb(4193250);
        }
    </style>
</head>

<body>
    <div class="parent">
        <div class="card">
            <div class="content-box">
                <span class="card-title">2025 <span class="subtitle">蛇年大吉</span></span>
                <p class="card-content">
                    祥龙降瑞留福韵,金蛇迎春展锦程
                </p>
                <span class="see-more">了解更多</span>
            </div>
            <div class="date-box">
                <span class="month">01</span>
                <span class="date">18</span>
            </div>
        </div>
    </div>
</body>

</html>

HTML 结构

  • parent: 创建一个类名为“parent”的 div 元素,用于包含卡片。
  • card: 创建一个类名为“card”的 div 元素,用于显示卡片内容。
  • content-box: 包含卡片的主要内容。
  • card-title: 显示卡片的标题和副标题。
  • card-content: 显示卡片的内容。
  • see-more: 显示“了解更多”按钮。
  • date-box: 包含日期信息。
  • month: 显示月份。
  • date: 显示日期。

CSS 样式

  • .parent: 设置卡片容器的样式,包括尺寸、内边距和 3D 透视效果。
  • .card: 设置卡片的样式,包括内边距、边框、背景渐变、尺寸和阴影。
  • .card:hover: 设置鼠标悬停在卡片上时的背景位置和 3D 旋转效果。
  • .content-box: 设置卡片内容的样式,包括背景、过渡效果和内边距。
  • .content-box .card-title: 设置卡片标题的样式,包括颜色、字体大小、权重和 3D 位置。
  • .content-box .card-title .subtitle: 设置副标题的样式,包括颜色、字体大小、权重和 3D 位置。
  • .content-box .card-title:hover: 设置鼠标悬停在标题上时的 3D 位置。
  • .content-box .card-content: 设置卡片内容的样式,包括字体大小、权重、颜色和 3D 位置。
  • .content-box .card-content:hover: 设置鼠标悬停在内容上时的 3D 位置。
  • .content-box .see-more: 设置“了解更多”按钮的样式,包括光标、内边距、字体大小、颜色和 3D 位置。
  • .content-box .see-more:hover: 设置鼠标悬停在按钮上时的 3D 位置。
  • .date-box: 设置日期框的样式,包括位置、尺寸、背景、边框、内边距、3D 位置和阴影。
  • .date-box span: 设置日期框内文本的样式,包括显示方式和对齐。
  • .date-box .month: 设置月份的样式,包括颜色、字体大小和权重。
  • .date-box .date: 设置日期的样式,包括字体大小和权重。

HTML&CSS:超丝滑的动态产品卡片

作者 前端Hardy
2025年1月16日 11:53

这段代码创建了一个具有动态效果的产品卡片,通过 CSS 技术实现了卡片的透明度变化、尺寸变化和位置变化效果,为页面添加了视觉吸引力和用户交互体验。

演示效果

HTML&CSS

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>公众号关注:前端Hardy</title>
    <style>
        body {
            margin0;
            padding0;
            background#212121;
            display: flex;
            align-items: center;
            justify-content: center;
            height100vh;
        }

        .card {
            position: relative;
            background: transparent;
            width300px;
            height300px;
            border: none;
        }

        .card:hover {
            width300px;
        }

        .card .container-image {
            position: absolute;
            top50%;
            left50%;
            transformtranslate(-50%, -50%);
            background#e7e7e7;
            width190px;
            height190px;
            cursor: pointer;
            border: none;
            border-radius50%;
            box-shadow0 0 3px 1px #1818183d2px 2px 3px #18181865, inset 2px 2px 2px #ffffff;
            transition: all .3s ease-in-out, opacity .3s;
            transition-delay: .6s0s;
        }

        .card:hover .container-image {
            opacity0;
            border-radius8px;
            transition-delay0s, .6s;
        }

        .card .container-image .image-circle {
            position: absolute;
            top50%;
            left50%;
            transformtranslate(-50%, -50%);
            width125px;
            height: auto;
            object-fit: contain;
            filterdrop-shadow(2px 2px 2px #1818188a);
            transition: all .3s ease-in-out;
            transition-delay: .4s;
        }

        .card:hover .container-image .image-circle {
            opacity0;
            transition-delay0s;
        }

        .card .content {
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: absolute;
            top50%;
            left50%;
            transformtranslate(-50%, -50%);
            background#e7e7e7;
            padding20px;
            width190px;
            height190px;
            cursor: pointer;
            border: none;
            border-radius8px;
            box-shadow0 0 3px 1px #1818183d2px 2px 3px #18181865, inset 2px 2px 2px #ffffff;
            visibility: hidden;
            transition: .3s ease-in-out;
            transition-delay0s;
            z-index1;
        }

        .card:hover .content {
            width290px;
            height190px;
            visibility: visible;
            transition-delay: .5s;
        }

        .card .content .detail {
            display: flex;
            flex-direction: column;
            width100%;
            height100%;
            opacity0;
            transition: all .3s ease-in-out;
            transition-delay0s;
        }

        .card:hover .content .detail {
            color#181818;
            opacity100%;
            transition1s;
            transition-delay: .3s;
        }

        .card .content .detail span {
            margin-bottom5px;
            font-size18px;
            font-weight800;
        }

        .card .content .detail button {
            background#b8854b;
            margin-top: auto;
            width75px;
            height25px;
            color#ffffff;
            font-size13px;
            border: none;
            border-radius8px;
            transition: .3s ease-in-out;
        }

        .card .content .detail button:hover {
            background#d39f63;
        }

        .card .content .product-image {
            position: relative;
            width100%;
            height100%;
        }

        .card .content .product-image .box-image {
            display: flex;
            position: absolute;
            top0;
            left: -25%;
            width100%;
            height115%;
            opacity0;
            transformscale(.5);
            transition: all .5s ease-in-out;
            transition-delay0s;
        }

        .card:hover .content .product-image .box-image {
            top: -25%;
            left0;
            opacity100%;
            transformscale(1);
            transition-delay: .3s;
        }

        .card .content .product-image .box-image .img-product {
            margin: auto;
            width7rem;
            height: auto;
        }

        .fil-shoes1,
        .fil-shoes2 {
            fill: #333333
        }
    </style>
</head>

<body>
    <div class="card">
        <div class="container-image">
            <svg class="image-circle" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" version="1.1"
                style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
                viewBox="0 0 335.76 195.21" xmlns:xlink="http://www.w3.org/1999/xlink">
                <defs></defs>
                <g id="Layer_x0020_1">
                    <metadata id="CorelCorpID_0Corel-Layer"></metadata>
                    <path class="fil-shoes1"
                        d="M332.99 147.72c-0.87,-8.61 -2.43,-5.69 -1.57,-16.93 0.7,-9.13 -0.29,-27.37 -1.46,-37.14 -0.23,-1.89 -0.43,-5.19 -1.06,-8.26l-3.31 -12.45c-0.54,-1.82 -0.16,-2.7 -0.7,-4.36 -1.5,-4.56 -2.81,-6.58 -3.32,-12.45 -0.27,-3.05 0.85,-4.81 -1.89,-7.13 -1.31,-1.11 -2.14,-1.33 -3.74,-1.23 -10.29,0.69 -19.1,-4.44 -28.23,-7.89l-5.37 -2.51c-7.84,-3.92 -16.02,-10.9 -23.59,-15.81 -5.06,-3.28 -2.36,-0.49 -4.87,-5.83 -2.48,-5.29 -11.1,-6.93 -16.27,-8.5 -2.53,-0.76 -1.72,-0.99 -3.98,-1.68 -1.14,-0.35 -3.14,-0.5 -3.63,-0.76 -2.09,-1.09 -7.48,-4.47 -9.41,-4.76 -3.83,-0.58 -7,6.85 -9.59,10.32 -1.8,2.42 -3.23,5.65 -3.64,8.83 -0.22,1.71 -1.74,3.48 -2.63,5.16 -8.27,-3.97 -8.47,-1.81 -9.27,0.86 -1.69,5.63 -4.59,10.52 -6.25,16.27 -3.05,10.56 -6.49,6.16 -11.04,12.04 -1.64,2.12 -0.97,2.39 -3.42,3.9 -5.38,3.33 -9.5,0.93 -16.05,7.03 -10.09,9.4 -3.03,2.62 -9.55,5.65 -1.43,0.66 -3.15,2.01 -4.26,3.06 -2.1,2.01 -1.92,2.22 -3.22,4.67 -11.67,0 -10.17,6.25 -14.88,7.64 -4.6,1.36 -6.75,1.85 -9.78,5.42 -1.14,1.35 -2.27,3.88 -3.22,4.66 -1.61,1.31 -2.53,0.56 -4.95,2.37 -3.18,2.38 -6.99,3.65 -9.48,5.71 -2.55,2.1 -1.2,1.6 -4.73,3.15 -5.39,2.38 -10.82,3.14 -15.13,7.39 -1.64,1.62 -16.4,4.41 -18.66,4.98 -11.91,3.03 -25.8,4.05 -37.36,8.24 -6.1,2.21 -4.85,-2.22 -11.16,4.05 -4.74,4.71 -3.68,10.8 -6.22,16.29 -1.07,2.31 -1.69,1.85 -2.68,5.2l-1.44 5.87c-0.73,4.22 -2.36,6.72 -1.86,12.16l1.02 4.62c1.95,5.05 7.38,8.45 12.31,10.21l13.44 4.02c5.09,1.37 11.26,1.47 16.51,2.63 5.72,1.26 34.16,1.33 39.85,0.87 2.59,-0.21 3.66,0.35 5.75,0.84 3.42,0.8 4.45,-0.44 7.03,-0.28 2.33,0.14 3.31,1.06 6.8,1.09 9.62,0.08 90.6,0.66 98.33,-0.28 4.23,-0.52 10.35,0.74 14.86,0.26 11.36,-1.21 24.28,-2.91 36.17,-1.87 7.05,0.61 29.63,1.01 33.07,-1.51 1.48,0.99 29.81,-0.46 33.72,-0.68 8.78,-0.5 17.29,-6.69 16.8,-15.89 -0.1,-9.37 -1.8,-17.8 -2.75,-27.26z">
                    </path>
                </g>
            </svg>
        </div>
        <div class="content">
            <div class="detail">
                <span>李宁 <br> 春节新款.</span>
                <p>¥299</p>
                <button>立即抢购</button>
            </div>
            <div class="product-image">
                <div class="box-image">
                    <svg class="img-product" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" version="1.1"
                        style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
                        viewBox="0 0 116.83 182.61" xmlns:xlink="http://www.w3.org/1999/xlink">
                        <defs></defs>
                        <g id="Layer_x0020_1">
                            <metadata id="CorelCorpID_0Corel-Layer"></metadata>
                            <path class="fil-shoes2"
                                d="M99.33 20.55c-4.24,-1.91 -3.3,-0.4 -8.3,-3.82 -4.06,-2.78 -12.82,-7.22 -17.68,-9.3 -0.94,-0.4 -2.53,-1.19 -4.13,-1.73l-6.69 -1.8c-0.99,-0.23 -1.3,-0.65 -2.22,-0.84 -2.53,-0.53 -3.82,-0.46 -6.69,-1.8 -1.49,-0.7 -2.01,-1.69 -3.83,-1.04 -0.87,0.31 -1.19,0.64 -1.58,1.41 -2.44,4.98 -7.2,7.7 -11.26,11.02l-2.61 1.83c-3.93,2.6 -9.38,4.53 -13.7,6.73 -2.89,1.47 -0.86,0.97 -4.02,0.7 -3.13,-0.27 -6.21,3.31 -8.33,5.29 -1.04,0.97 -0.92,0.53 -1.85,1.4 -0.47,0.44 -1.08,1.33 -1.33,1.49 -1.07,0.68 -4.09,2.28 -4.75,3.1 -1.3,1.63 1.31,5.1 2.23,7.24 0.64,1.49 1.76,3.02 3.13,4.07 0.74,0.56 1.15,1.74 1.7,2.61 -4.07,2.78 -3.12,3.46 -2.09,4.55 2.17,2.3 3.66,4.97 5.89,7.28 4.1,4.26 1.12,4.68 2.64,8.38 0.55,1.33 0.85,1.09 0.9,2.64 0.11,3.4 -2.12,4.67 -1.04,9.36 1.66,7.23 0.4,2.11 0.06,5.96 -0.07,0.84 0.09,2.01 0.28,2.8 0.37,1.51 0.52,1.49 1.31,2.75 -3.14,5.43 0.18,6.41 -0.44,8.98 -0.6,2.51 -0.95,3.64 -0.11,6.01 0.32,0.9 1.2,2.1 1.3,2.75 0.18,1.1 -0.42,1.33 -0.22,2.94 0.25,2.12 -0.18,4.23 0.11,5.95 0.29,1.75 0.42,0.99 0.2,3.05 -0.34,3.15 -1.45,5.88 -0.63,9.03 0.31,1.2 -2.36,8.82 -2.7,10.03 -1.79,6.36 -5.05,13.1 -6.2,19.61 -0.61,3.43 -2.34,1.66 -1.11,6.28 0.92,3.47 4.04,4.61 5.91,7.28 0.79,1.12 0.41,1.28 1.7,2.65l2.35 2.25c1.77,1.48 2.49,2.9 5.16,4.13l2.42 0.76c2.87,0.45 5.92,-1.16 8.06,-2.98l5.48 -5.18c2.01,-2 3.71,-4.85 5.66,-6.98 2.12,-2.32 9.8,-15.54 11.11,-18.32 0.6,-1.26 1.15,-1.61 1.93,-2.45 1.29,-1.38 0.99,-2.19 1.76,-3.35 0.69,-1.05 1.38,-1.26 2.33,-2.87 2.62,-4.45 24.66,-42 26.3,-45.85 0.9,-2.11 3.13,-4.62 4.12,-6.85 2.49,-5.61 5.17,-12.08 8.85,-17.34 2.18,-3.12 8.43,-13.52 8.19,-15.8 0.86,-0.42 7.8,-14 8.75,-15.88 2.13,-4.22 1.53,-9.85 -2.88,-12.09 -4.39,-2.47 -8.77,-3.95 -13.43,-6.05z">
                            </path>
                        </g>
                    </svg>
                </div>
            </div>
        </div>
    </div>
</body>

</html>

HTML 结构

  • card: 创建一个类名为“card”的 div 元素,用于包含整个产品卡片。
  • container-image: 包含圆形图片的 div。
  • image-circle: 创建一个 SVG 圆形图片。
  • content: 包含产品详细信息的 div。
  • detail: 包含产品名称、价格和购买按钮的 div。
  • product-image: 包含产品图片的 div。
  • box-image: 包含 SVG 产品图片的 div。

CSS 样式

  • .card: 设置卡片的样式,包括位置、背景、尺寸和边框。
  • .card:hover: 设置鼠标悬停在卡片上时的样式。
  • .container-image: 设置圆形图片容器的样式,包括位置、背景、尺寸、边框半径和阴影。
  • .card:hover .container-image: 设置鼠标悬停在卡片上时圆形图片容器的样式,使其透明度变为 0。
  • .image-circle: 设置圆形图片的样式,包括位置、尺寸和滤镜效果。
  • .card:hover .container-image .image-circle: 设置鼠标悬停在卡片上时圆形图片的样式,使其透明度变为 0。
  • .content: 设置产品详细信息容器的样式,包括位置、背景、尺寸、边框半径和可见性。
  • .card:hover .content: 设置鼠标悬停在卡片上时产品详细信息容器的样式,使其可见并调整尺寸。
  • .detail: 设置产品详细信息的样式,包括显示方式、尺寸和透明度。
  • .card:hover .content .detail: 设置鼠标悬停在卡片上时产品详细信息的样式,使其可见。
  • .detail span: 设置产品名称的样式,包括字体大小和权重。
  • .detail button: 设置购买按钮的样式,包括背景、尺寸、颜色和边框半径。
  • .detail button:hover: 设置鼠标悬停在购买按钮上时的样式。
  • .product-image: 设置产品图片容器的样式,包括位置和尺寸。
  • .box-image: 设置产品图片的样式,包括位置、尺寸和透明度。
  • .card:hover .content .product-image .box-image: 设置鼠标悬停在卡片上时产品图片的样式,使其可见并调整位置和尺寸。
  • .img-product: 设置产品图片的样式,包括尺寸。

HTML&CSS:超级使用的点赞特效卡片!建议收藏

作者 前端Hardy
2025年1月16日 11:53

这段代码是一个 HTML 页面,它包含了 CSS 样式,用于创建一个带有“点赞”和“不喜欢”功能的交互式卡片。卡片上有一个关闭按钮,用户可以点击“点赞”或“不喜欢”按钮,并且有动画效果。

演示效果

HTML&CSS

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>公众号关注:前端Hardy</title>
    <style>
        body {
            margin0;
            padding0;
            background#e8e8e8;
            display: flex;
            align-items: center;
            justify-content: center;
            height100vh;
        }

        .like-dislike-container {
            --dark-grey#353535;
            --middle-grey#767676;
            --lightest-greylinear-gradient(#fafafa#ebebeb);
            --shadow0 5px 15px 0 #00000026;
            --shadow-active0 5px 5px 0 #00000026;
            --border-radius-main10px;
            --border-radius-icon50px;
            position: relative;
            display: flex;
            text-align: center;
            flex-direction: column;
            align-items: center;
            cursor: default;
            colorvar(--dark-grey);
            opacity: .9;
            margin: auto;
            padding1.5rem;
            font-weight600;
            backgroundvar(--lightest-grey);
            max-width: max-content;
            border-radiusvar(--border-radius-main);
            box-shadowvar(--shadow);
            transition: .2s ease all;
        }

        .like-dislike-container:hover {
            box-shadowvar(--shadow-active);
        }

        .like-dislike-container .tool-box {
            position: absolute;
            display: flex;
            align-items: center;
            justify-content: center;
            width2.5rem;
            height2.5rem;
            top0;
            right0;
            border-radiusvar(--border-radius-main);
        }

        .like-dislike-container .btn-close {
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
            width: .8rem;
            height: .8rem;
            color: transparent;
            font-size0;
            cursor: pointer;
            background-color#ff000080;
            border: none;
            border-radiusvar(--border-radius-main);
            transition: .2s ease all;
        }

        .like-dislike-container .btn-close:hover {
            width1rem;
            height1rem;
            font-size1rem;
            color#ffffff;
            background-color#ff0000cc;
            box-shadowvar(--shadow-active);
        }

        .like-dislike-container .btn-close:active {
            width: .9rem;
            height: .9rem;
            font-size: .9rem;
            color#ffffffde;
            --shadow-btn-close0 3px 3px 0 #00000026;
            box-shadowvar(--shadow-btn-close);
        }

        .like-dislike-container .text-content {
            margin-bottom1rem;
            font-size15px;
            line-height1.6;
            cursor: default;
        }

        .like-dislike-container .icons-box {
            display: flex;
        }

        .like-dislike-container .icons {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: .6;
            margin0 0.5rem;
            cursor: pointer;
            user-select: none;
            border1px solid var(--middle-grey);
            border-radiusvar(--border-radius-icon);
            transition: .2s ease all;
        }

        .like-dislike-container .icons:hover {
            opacity: .9;
            box-shadowvar(--shadow);
        }

        .like-dislike-container .icons:active {
            opacity: .9;
            box-shadowvar(--shadow-active);
        }

        .like-dislike-container .icons .btn-label {
            display: flex;
            justify-content: center;
            align-items: center;
            padding0 0.5rem;
            cursor: pointer;
            position: relative;
        }

        .like-dislike-container .like-text-content {
            border-right0.1rem solid var(--dark-grey);
            padding0 0.6rem 0 0.5rem;
            pointer-events: none;
        }

        .like-dislike-container .dislike-text-content {
            border-left0.1rem solid var(--dark-grey);
            padding0 0.5rem 0 0.6rem;
            pointer-events: none;
        }

        .like-dislike-container .icons .svgs {
            width1.3rem;
            fill: #000000;
            box-sizing: content-box;
            padding10px 10px;
            transition: .2s ease all;
        }

        .like-dislike-container .icons .input-box {
            position: absolute;
            opacity0;
            cursor: pointer;
            height0;
            width0;
        }

        .like-dislike-container .icons #icon-like-regular {
            display: block;
        }

        .like-dislike-container .icons #icon-like-solid {
            display: none;
        }

        .like-dislike-container .icons:hover :is(#icon-like-solid#icon-like-regular) {
            animation: rotate-icon-like 0.7s ease-in-out both;
        }

        .like-dislike-container .icons #like-checkbox:checked~#icon-like-regular {
            display: none;
            animation: checked-icon-like 0.5s;
        }

        .like-dislike-container .icons #like-checkbox:checked~#icon-like-solid {
            display: block;
            animation: checked-icon-like 0.5s;
        }

        .like-dislike-container .icons #icon-dislike-regular {
            display: block;
            transformrotate(180deg);
        }

        .like-dislike-container .icons #icon-dislike-solid {
            display: none;
            transformrotate(180deg);
        }

        .like-dislike-container .icons:hover :is(#icon-dislike-solid#icon-dislike-regular) {
            animation: rotate-icon-dislike 0.7s ease-in-out both;
        }

        .like-dislike-container .icons #dislike-checkbox:checked~#icon-dislike-regular {
            display: none;
            animation: checked-icon-dislike 0.5s;
        }

        .like-dislike-container .icons #dislike-checkbox:checked~#icon-dislike-solid {
            display: block;
            animation: checked-icon-dislike 0.5s;
        }

        .like-dislike-container .icons .fireworks {
            transformscale(0.4);
        }

        .like-dislike-container .icons #like-checkbox:checked~.fireworks>.checked-like-fx {
            position: absolute;
            width10px;
            height10px;
            right40px;
            border-radius50%;
            box-shadow0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff;
            animation1s fireworks-bang ease-out forwards, 1s fireworks-gravity ease-in forwards, 5s fireworks-position linear forwards;
            animation-duration1.25s1.25s6.25s;
        }

        .like-dislike-container .icons #dislike-checkbox:checked~.fireworks>.checked-dislike-fx {
            position: absolute;
            width10px;
            height10px;
            left40px;
            border-radius50%;
            box-shadow0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff0 0 #fff;
            animation1s fireworks-bang ease-out forwards, 1s fireworks-gravity ease-in forwards, 5s fireworks-position linear forwards;
            animation-duration1.25s1.25s6.25s;
        }

        @keyframes rotate-icon-like {
            0% {
                transformrotate(0degtranslate3d(000);
            }

            25% {
                transformrotate(3degtranslate3d(000);
            }

            50% {
                transformrotate(-3degtranslate3d(000);
            }

            75% {
                transformrotate(1degtranslate3d(000);
            }

            100% {
                transformrotate(0degtranslate3d(000);
            }
        }

        @keyframes rotate-icon-dislike {
            0% {
                transformrotate(180degtranslate3d(000);
            }

            25% {
                transformrotate(183degtranslate3d(000);
            }

            50% {
                transformrotate(177degtranslate3d(000);
            }

            75% {
                transformrotate(181degtranslate3d(000);
            }

            100% {
                transformrotate(180degtranslate3d(000);
            }
        }

        @keyframes checked-icon-like {
            0% {
                transformscale(0);
                opacity0;
            }

            50% {
                transformscale(1.2rotate(-10deg);
            }
        }

        @keyframes checked-icon-dislike {
            0% {
                transformscale(0rotate(180deg);
                opacity0;
            }

            50% {
                transformscale(1.2rotate(170deg);
            }
        }

        @keyframes fireworks-position {

            0%,
            19.9% {
                margin-top10%;
                margin-left40%;
            }

            20%,
            39.9% {
                margin-top40%;
                margin-left30%;
            }

            40%,
            59.9% {
                margin-top20%;
                margin-left70%;
            }

            60%,
            79.9% {
                margin-top30%;
                margin-left20%;
            }

            80%,
            99.9% {
                margin-top30%;
                margin-left80%;
            }
        }

        @keyframes fireworks-gravity {
            to {
                transformtranslateY(200px);
                opacity0;
            }
        }

        @keyframes fireworks-bang {
            to {
                box-shadow114px -107.3333333333px #8800ff212px -166.3333333333px #a600ff197px -6.3333333333px #ff006a179px -329.3333333333px #3300ff, -167px -262.3333333333px #ff0062233px 65.6666666667px #ff008c81px 42.6666666667px #0051ff, -13px 54.6666666667px #00ff2b, -60px -183.3333333333px #0900ff127px -259.3333333333px #ff00e6117px -122.3333333333px #00b7ff95px 20.6666666667px #ff8000115px 1.6666666667px #0004ff, -160px -328.3333333333px #00ff4069px -242.3333333333px #000dff, -208px -230.3333333333px #ff040030px -15.3333333333px #e6ff00235px -15.3333333333px #fb00ff80px -232.3333333333px #d5ff00175px -173.3333333333px #00ff3c, -187px -176.3333333333px #aaff004px 26.6666666667px #ff6f00227px -106.3333333333px #ff0099119px 17.6666666667px #00ffd5, -102px 4.6666666667px #ff0088, -16px -4.3333333333px #00fff7, -201px -310.3333333333px #00ffdd64px -181.3333333333px #f700ff, -234px -15.3333333333px #00fffb, -184px -263.3333333333px #aa00ff96px -303.3333333333px #0037ff, -139px 10.6666666667px #0026ff25px -205.3333333333px #00ff2b, -129px -322.3333333333px #40ff00, -235px -187.3333333333px #26ff00, -136px -237.3333333333px #0091ff, -82px -321.3333333333px #6a00ff7px -267.3333333333px #ff00c8, -155px 30.6666666667px #0059ff, -85px -73.3333333333px #6a00ff60px -199.3333333333px #55ff00, -9px -289.3333333333px #00ffaa, -208px -167.3333333333px #00ff80, -13px -299.3333333333px #ff0004179px -164.3333333333px #ff0044, -112px 12.6666666667px #0051ff, -209px -125.3333333333px #ff00bb14px -101.3333333333px #00ff95, -184px -292.3333333333px #ff0099, -26px -168.3333333333px #09ff00129px -67.3333333333px #0084ff, -17px -23.3333333333px #0059ff129px 34.6666666667px #7300ff35px -24.3333333333px #ffd900, -12px -297.3333333333px #ff8400129px -156.3333333333px #0dff00157px -29.3333333333px #1a00ff, -221px 6.6666666667px #ff00620px -311.3333333333px #ff006a155px 50.6666666667px #00ffaa, -71px -318.3333333333px #0073ff;
            }
        }
    </style>
</head>

<body>
    <div class="like-dislike-container">
        <div class="tool-box">
            <button class="btn-close">×</button>
        </div>
        <p class="text-content">您觉得这篇文章<br>怎么样?</p>
        <div class="icons-box">
            <div class="icons">
                <label class="btn-label" for="like-checkbox">
                    <span class="like-text-content">123</span>
                    <input class="input-box" id="like-checkbox" type="checkbox">
                    <svg class="svgs" id="icon-like-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                        <path
                            d="M313.4 32.9c26 5.2 42.9 30.5 37.7 56.5l-2.3 11.4c-5.3 26.7-15.1 52.1-28.8 75.2H464c26.5 0 48 21.5 48 48c0 18.5-10.5 34.6-25.9 42.6C497 275.4 504 288.9 504 304c0 23.4-16.8 42.9-38.9 47.1c4.4 7.3 6.9 15.8 6.9 24.9c0 21.3-13.9 39.4-33.1 45.6c.7 3.3 1.1 6.8 1.1 10.4c0 26.5-21.5 48-48 48H294.5c-19 0-37.5-5.6-53.3-16.1l-38.5-25.7C176 420.4 160 390.4 160 358.3V320 272 247.1c0-29.2 13.3-56.7 36-75l7.4-5.9c26.5-21.2 44.6-51 51.2-84.2l2.3-11.4c5.2-26 30.5-42.9 56.5-37.7zM32 192H96c17.7 0 32 14.3 32 32V448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32V224c0-17.7 14.3-32 32-32z">
                        </path>
                    </svg>
                    <svg class="svgs" id="icon-like-regular" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                        <path
                            d="M323.8 34.8c-38.2-10.9-78.1 11.2-89 49.4l-5.7 20c-3.7 13-10.4 25-19.5 35l-51.3 56.4c-8.9 9.8-8.2 25 1.6 33.9s25 8.2 33.9-1.6l51.3-56.4c14.1-15.5 24.4-34 30.1-54.1l5.7-20c3.6-12.7 16.9-20.1 29.7-16.5s20.1 16.9 16.5 29.7l-5.7 20c-5.7 19.9-14.7 38.7-26.6 55.5c-5.2 7.3-5.8 16.9-1.7 24.9s12.3 13 21.3 13L448 224c8.8 0 16 7.2 16 16c0 6.8-4.3 12.7-10.4 15c-7.4 2.8-13 9-14.9 16.7s.1 15.8 5.3 21.7c2.5 2.8 4 6.5 4 10.6c0 7.8-5.6 14.3-13 15.7c-8.2 1.6-15.1 7.3-18 15.1s-1.6 16.7 3.6 23.3c2.1 2.7 3.4 6.1 3.4 9.9c0 6.7-4.2 12.6-10.2 14.9c-11.5 4.5-17.7 16.9-14.4 28.8c.4 1.3 .6 2.8 .6 4.3c0 8.8-7.2 16-16 16H286.5c-12.6 0-25-3.7-35.5-10.7l-61.7-41.1c-11-7.4-25.9-4.4-33.3 6.7s-4.4 25.9 6.7 33.3l61.7 41.1c18.4 12.3 40 18.8 62.1 18.8H384c34.7 0 62.9-27.6 64-62c14.6-11.7 24-29.7 24-50c0-4.5-.5-8.8-1.3-13c15.4-11.7 25.3-30.2 25.3-51c0-6.5-1-12.8-2.8-18.7C504.8 273.7 512 257.7 512 240c0-35.3-28.6-64-64-64l-92.3 0c4.7-10.4 8.7-21.2 11.8-32.2l5.7-20c10.9-38.2-11.2-78.1-49.4-89zM32 192c-17.7 0-32 14.3-32 32V448c0 17.7 14.3 32 32 32H96c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32H32z">
                        </path>
                    </svg>
                    <div class="fireworks">
                        <div class="checked-like-fx"></div>
                    </div>
                </label>
            </div>
            <div class="icons">
                <label class="btn-label" for="dislike-checkbox">
                    <input class="input-box" id="dislike-checkbox" type="checkbox">
                    <div class="fireworks">
                        <div class="checked-dislike-fx"></div>
                    </div>
                    <svg class="svgs" id="icon-dislike-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                        <path
                            d="M313.4 32.9c26 5.2 42.9 30.5 37.7 56.5l-2.3 11.4c-5.3 26.7-15.1 52.1-28.8 75.2H464c26.5 0 48 21.5 48 48c0 18.5-10.5 34.6-25.9 42.6C497 275.4 504 288.9 504 304c0 23.4-16.8 42.9-38.9 47.1c4.4 7.3 6.9 15.8 6.9 24.9c0 21.3-13.9 39.4-33.1 45.6c.7 3.3 1.1 6.8 1.1 10.4c0 26.5-21.5 48-48 48H294.5c-19 0-37.5-5.6-53.3-16.1l-38.5-25.7C176 420.4 160 390.4 160 358.3V320 272 247.1c0-29.2 13.3-56.7 36-75l7.4-5.9c26.5-21.2 44.6-51 51.2-84.2l2.3-11.4c5.2-26 30.5-42.9 56.5-37.7zM32 192H96c17.7 0 32 14.3 32 32V448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32V224c0-17.7 14.3-32 32-32z">
                        </path>
                    </svg>
                    <svg class="svgs" id="icon-dislike-regular" xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 512 512">
                        <path
                            d="M323.8 34.8c-38.2-10.9-78.1 11.2-89 49.4l-5.7 20c-3.7 13-10.4 25-19.5 35l-51.3 56.4c-8.9 9.8-8.2 25 1.6 33.9s25 8.2 33.9-1.6l51.3-56.4c14.1-15.5 24.4-34 30.1-54.1l5.7-20c3.6-12.7 16.9-20.1 29.7-16.5s20.1 16.9 16.5 29.7l-5.7 20c-5.7 19.9-14.7 38.7-26.6 55.5c-5.2 7.3-5.8 16.9-1.7 24.9s12.3 13 21.3 13L448 224c8.8 0 16 7.2 16 16c0 6.8-4.3 12.7-10.4 15c-7.4 2.8-13 9-14.9 16.7s.1 15.8 5.3 21.7c2.5 2.8 4 6.5 4 10.6c0 7.8-5.6 14.3-13 15.7c-8.2 1.6-15.1 7.3-18 15.1s-1.6 16.7 3.6 23.3c2.1 2.7 3.4 6.1 3.4 9.9c0 6.7-4.2 12.6-10.2 14.9c-11.5 4.5-17.7 16.9-14.4 28.8c.4 1.3 .6 2.8 .6 4.3c0 8.8-7.2 16-16 16H286.5c-12.6 0-25-3.7-35.5-10.7l-61.7-41.1c-11-7.4-25.9-4.4-33.3 6.7s-4.4 25.9 6.7 33.3l61.7 41.1c18.4 12.3 40 18.8 62.1 18.8H384c34.7 0 62.9-27.6 64-62c14.6-11.7 24-29.7 24-50c0-4.5-.5-8.8-1.3-13c15.4-11.7 25.3-30.2 25.3-51c0-6.5-1-12.8-2.8-18.7C504.8 273.7 512 257.7 512 240c0-35.3-28.6-64-64-64l-92.3 0c4.7-10.4 8.7-21.2 11.8-32.2l5.7-20c10.9-38.2-11.2-78.1-49.4-89zM32 192c-17.7 0-32 14.3-32 32V448c0 17.7 14.3 32 32 32H96c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32H32z">
                        </path>
                    </svg>
                    <span class="dislike-text-content">4</span>
                </label>
            </div>
        </div>
    </div>
</body>

</html>

HTML 结构

  • like-dislike-container: 创建一个类名为“like-dislike-container”的 div 元素,用于包含整个卡片。
  • tool-box: 包含工具栏的 div。
  • btn-close: 创建一个关闭按钮。
  • text-content: 显示文本“您觉得这篇文章怎么样?”。
  • icons-box: 包含“点赞”和“不喜欢”按钮的 div。
  • icons: 元素,每个元素包含一个按钮。
  • btn-label: 创建一个标签,用于“点赞”按钮。
  • input-box like-checkbox : 创建一个复选框,用于“点赞”状态。
  • svgs: 创建两个 SVG 图标,一个用于“点赞”状态,一个用于默认状态。
  • fireworks: 创建一个用于显示烟花效果的 div。
  • btn-label: 创建一个标签,用于“不喜欢”按钮。
  • input-box: 创建一个复选框,用于“不喜欢”状态。
  • svgs icon-dislike-solid: 创建两个 SVG 图标,一个用于“不喜欢”状态,一个用于默认状态。

CSS 样式

  • .like-dislike-container: 设置卡片的样式,包括尺寸、背景渐变、边框半径、阴影和鼠标指针样式。
  • .like-dislike-container:hover: 设置鼠标悬停在卡片上时的阴影效果。
  • .tool-box: 设置工具栏的样式,包括位置、尺寸和对齐。
  • .btn-close: 设置关闭按钮的样式,包括尺寸、颜色、字体大小和鼠标指针样式。
  • .btn-close:hover 和 .btn-close:active: 设置关闭按钮在鼠标悬停和点击时的样式。
  • .text-content: 设置文本内容的样式,包括字体大小和行高。
  • .icons-box: 设置图标盒子的样式,包括显示方式。
  • .icons: 设置图标的样式,包括位置、尺寸、透明度和鼠标指针样式。
  • .icons:hover 和 .icons:active: 设置图标在鼠标悬停和点击时的样式。
  • .btn-label: 设置按钮标签的样式,包括位置和尺寸。
  • .like-text-content 和 .dislike-text-content: 设置“点赞”和“不喜欢”文本的样式,包括边框和内边距。
  • .svgs: 设置 SVG 图标的样式,包括尺寸和填充。
  • .input-box: 设置复选框的样式,包括位置和透明度。
  • .fireworks: 设置烟花效果的样式,包括位置和尺寸。
  • @keyframes rotate-icon-like 和 @keyframes rotate-icon-dislike: 定义图标旋转的动画效果。
  • @keyframes checked-icon-like 和 @keyframes checked-icon-dislike: 定义图标选中状态的动画效果。
  • @keyframes fireworks-position, @keyframes fireworks-gravity, @keyframes fireworks-bang: 定义烟花效果的动画效果。
❌
❌