漂亮的CSS移动端底部导航栏实现

先看效果:

chrome-capture (1).gif

这个效果的实现,重点是使用了svg滤镜

完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html,body{
      margin: 0;
      background-color: #e0e0e0;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
    }
    #box{
      width: 320px;
      height: 640px;
      background-color: #efefef;
      position: relative;
    }
    .footer{
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      display: flex;
      justify-content: space-between;
      background-color: #fff;
      background-image: linear-gradient(45deg, #ffe8e8, #ffffff, #edf9ff);
    }
    .tag{
      display: block;
      height: 60px;
      display: flex;
      align-items: center;
      justify-content: center;
      text-align: center;
      flex: 1;
      position: relative;
      z-index: 4;
      cursor: pointer;
    }
    .tag span{
      position: relative;
      top: 0;
      border-radius: 50%;
      transition: 0.6s;
      display: flex;
      width: 60px;
      height: 60px;
      align-items: center;
      justify-content: center;
      color: #a9b5bf;
    }
    .tag.current span{
      top: -20px;
      box-shadow: 0 2px 3px rgba(0, 0, 0, 0.05);
      background-image: linear-gradient(45deg, #ffe8e8, #ffffff, #edf9ff);
    }
    .tag span svg{
      width: 24px;
      fill: #a9b5bf;
    }
    .tag.current span svg{
      fill: #5b6c7a;
    }
    .footer-bg{
      position: absolute;
      left: 0;
      right: 0;
      bottom: 60px;
      height: 60px;
      background-color: #efefef;
      z-index: 2;
      filter: url(#goo);
      transition: 0.3s;
    }
    .dot{
      width: 78px;
      height: 64px;
      background-color: #efefef;
      position: absolute;
      left: 0%;
      top: 46px;
      transform: translateX(1px);
      border-radius: 50%;
      transition: 0.3s;
    }
    .content{
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 60px;
      z-index: 3;
      transition: background-color 0.3s;
      text-align: center;
      color: #fff;
    }
  </style>
</head>
<body>
  <div id="box">
    <div class="content">
      <main>
        <h1>Text</h1>
        <p>content position here</p>
        <p>click & next</p>
      </main>
    </div>
    <div class="footer-bg">
      <div class="dot"></div>
    </div>
    <footer class="footer">
      <div onclick="setCurrent(1)" class="tag tag1 current"><span><svg t="1697425088462" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4895" width="200" height="200"><path d="M900.745478 430.904767l-330.418307-308.008394c-16.679524-19.033077-40.82902-29.982212-66.411112-29.982212-25.172779 0-49.322274 10.846807-65.2855 28.8566L120.491656 430.802438c-15.860897 16.270211-20.465674 39.805736-11.665434 60.783052 8.80024 20.977316 29.163585 34.075347 51.880484 34.075347l28.651944 0 0 314.148096c0 48.708304 38.987109 88.309383 87.695413 88.309383l136.608374 0c17.702808 0 33.461377-14.325972 33.461377-32.02878L447.123813 687.032677c0-8.902568 5.832717-16.781853 14.735285-16.781853l96.393325 0c8.902568 0 15.656241 7.981613 15.656241 16.781853l0 208.954532c0 17.805136 14.837614 32.02878 32.540422 32.02878l136.608374 0c48.708304 0 88.616369-39.498751 88.616369-88.309383l0-314.148096 28.549615 0c22.61457 0 42.977915-13.098031 51.778155-33.973019C921.006495 470.812831 916.504047 447.174978 900.745478 430.904767L900.745478 430.904767 900.745478 430.904767M900.745478 430.904767 900.745478 430.904767z" p-id="4896"></path></svg></span></div>
      <div onclick="setCurrent(2)" class="tag tag2"><span><svg t="1697425146769" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10385" width="200" height="200"><path d="M697.995 113.419c-70.292-0.023-137.597 28.416-186.521 78.81-48.918-50.405-116.223-78.845-186.521-78.81-143.994 0-261.128 117.81-261.128 262.588 0 60.857 21.186 120.158 61.737 169.399l333.351 342.183a72.81 72.81 0 0 0 52.561 22.307c19.958 0 38.61-7.934 52.602-22.272l335.439-344.606c38.559-47.143 59.62-106.142 59.608-167.011 0-144.779-117.132-262.588-261.128-262.588" p-id="10386"></path></svg></span></div>
      <div onclick="setCurrent(3)" class="tag tag3"><span><svg t="1697425204633" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17807" width="200" height="200"><path d="M554.6 319c79.3 0 119-39.7 119-119S634 80.9 554.6 80.9c-79.3 0-119 39.7-119 119.1s39.7 119 119 119z m-303.4 0c79.3 0 119-39.7 119-119s-39.7-119.1-119-119.1-119 39.7-119 119.1 39.6 119 119 119zM908 409.4c-29.2-10-71.2 22.5-71.2 22.5l-130.2 110c-34.9-126-139.8-189.1-314.8-189.1C173.3 352.9 64 451.2 64 647.9 64 844.6 173.3 943 391.8 943c171.4 0 275.6-60.6 312.6-181.6l116.7 119.2s54.3 33.9 83.5 24.2c34.7-11.6 55.3-67.1 55.3-67.1V470.8c0.1 0-24.6-52-51.9-61.4z" p-id="17808"></path></svg></span></div>
      <div onclick="setCurrent(4)" class="tag tag4"><span><svg t="1697425179323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15873" width="200" height="200"><path d="M849.285816 446.006983c0-216.528522-175.531805-392.065444-392.065444-392.065444-216.528522 0-392.065444 175.536922-392.065444 392.065444 0 212.83848 169.602769 386.054543 381.026016 391.899668l-25.116027 122.098849 264.222777-195.065697-0.019443 0.005117C784.570909 693.817975 849.285816 577.470107 849.285816 446.006983L849.285816 446.006983zM467.13314 689.13635c-4.620227 0-9.250688-0.098237-13.896498-0.294712-86.150102-3.632737-165.779697-40.636512-224.213551-104.208387l17.995863-30.619368c54.015218 58.760289 127.618563 92.971461 207.246111 96.326882 79.639828 3.359514 155.851581-24.548092 214.611869-78.564333l16.542768 32.077579C625.272833 659.136082 548.224016 689.13635 467.13314 689.13635L467.13314 689.13635zM467.13314 689.13635" p-id="15874"></path></svg></span></div>
    </footer>
  </div>
  <svg width="0" height="0">
    <defs>
        <filter id="goo">
            <feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur" id="blurFilter"></feGaussianBlur>
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 30 -15" result="goo"></feColorMatrix>
            <feComposite in="SourceGraphic" in2="goo" operator="atop"></feComposite>
        </filter>
    </defs>
</svg>
<script>
function setCurrent(index) {
  const tags = document.querySelectorAll('.tag')
  tags.forEach(tag => {
    tag.classList.remove('current')
  })
  const tag = document.querySelector('.tag' + index)
  tag.classList.add('current')
  const dot = document.querySelector('.dot')
  dot.style.left = 25 * (index-1) + '%'
  setColor(index)
}

function setColor(index) {
  const colors = ['#a9b5bf', '#a9bfb7', '#bcbfa9', '#bfa9a9']
  const color = colors[index-1]
  const bg = document.querySelector('.footer-bg')
  const dot = document.querySelector('.dot')
  const content = document.querySelector('.content')
  const svg = document.querySelector('.tag.current span svg')
  bg.style.backgroundColor = color
  dot.style.backgroundColor = color
  content.style.backgroundColor = color
  const svgs = document.querySelectorAll('.tag span svg')
  svgs.forEach(svg => {
    svg.style.fill = '#a9b5bf'
  })
  svg.style.fill = color
}

setCurrent(1)
</script>
</body>
</html>

导航的平滑圆角融合实现:

1. SVG滤镜

  <svg width="0" height="0">
    <defs>
        <filter id="goo">
            <feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur" id="blurFilter"></feGaussianBlur>
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 30 -15" result="goo"></feColorMatrix>
            <feComposite in="SourceGraphic" in2="goo" operator="atop"></feComposite>
        </filter>
    </defs>
  </svg>

2. 使用滤镜的DOM

    <div class="footer-bg">
      <div class="dot"></div>
    </div>

3. 用CSS给DOM添加SVG滤镜

    .footer-bg{
      filter: url(#goo);
    }

4. 控制融合效果偏移位置JS

function setCurrent(index) {
  const tags = document.querySelectorAll('.tag')
  tags.forEach(tag => {
    tag.classList.remove('current')
  })
  const tag = document.querySelector('.tag' + index)
  tag.classList.add('current')
  const dot = document.querySelector('.dot')
  dot.style.left = 25 * (index-1) + '%'
  setColor(index)
}

这4点是实现的主要内容。其它代码看完整代码吧。

2023-10-16 11:08:41 184 0

参与讨论

选择你的头像