【问题标题】:Can I do a wipe transition using CSS?我可以使用 CSS 进行擦除过渡吗?
【发布时间】:2021-03-15 14:12:38
【问题描述】:

我有以下示例代码的 sn-p(我正在使用 React,但不想在此处发布之前花时间清理实际项目代码):

let menuOpened = false;

document.getElementById('menu-button')
    .addEventListener('click', function() {
      menuOpened = !menuOpened;
      document.getElementById('body').classList.toggle('menu-opened', menuOpened);
      document.getElementById('menu').classList.toggle('menu-opened', menuOpened);
    });
* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

body.menu-opened {
  overflow-y: hidden;
}

body > * {
  width: 100vw;
}

header {
  background-color: #6FC5C2;
  display: flex;
  height: 20vh;
  position: sticky;
  top: 0;
  
  align-items: center;
  justify-content: center;
}

nav {
  background-color: #80CAF1;
  display: flex;
  height: 80vh;
  left: 0;
  opacity: 0;
  padding: 1rem;
  position: fixed;
  top: 20vh;
  transition: all 0.35s ease;
  visibility: hidden;
  z-index: 20;
  
  align-items: center;
  flex-direction: column;
  justify-content: center;
}

nav.menu-opened {
  opacity: 1;
  visibility: visible;
}

a {
  color: black;
  font-weight: bold;
  text-decoration: none;
}

a:not(:last-child) {
  margin-bottom: 0.5rem;
}

main {
  display: flex;
}

aside {
  background-color: #9C9ECF;
  display: flex;
  flex-basis: 25%;
  padding: 3rem 0.5rem;
  text-align: center;
  
  justify-content: center;
}

section {
  background-color: #F8CFD7;
  display: flex;
  flex-basis: 75%;
  padding: 2rem;
  
  align-items: stretch;
  flex-direction: column;
}

article {
  border: ridge #80CAF1;
  border-width: 3px 3px 0 3px;
  display: flex;
  font-size: 0.75rem;
  min-height: 15vh;
  padding: 1rem;
  
  align-items: center;
}

article:last-child {
  border-width: 3px;
}

footer {
  background-color: #016CBA;
  height: 30vh;
}
<body id="body">
  <header>
    <button id="menu-button" type="button">Menu</button>
  </header>
  <nav id="menu">
    <a href="/">Link 1</a>
    <a href="/">Link 2</a>
  </nav>
  <main id="main">
    <aside>Filter Form</aside>
    <section>
      <article>Article A</article>
      <article>Article B</article>
      <article>Article C</article>
      <article>Article D</article>
      <article>Article E</article>
      <article>Article F</article>
      <article>Article G</article>
      <article>Article H</article>
      <article>Article I</article>
    </section>
  </main>
  <footer id="footer"></footer>
</body>

目前,当我点击按钮打开导航菜单时,页面将禁用滚动,菜单将淡入。当我再次点击按钮时,将重新启用滚动,菜单将淡出。

我真正想要的是一个擦除过渡而不是褪色,就像这样:

以上图为例,主页内容为 A,菜单为 B。但是,我希望擦除不是水平的,而是垂直的,即当我打开菜单时,擦除将从从上到下,当我关闭菜单时,擦除将从下到上。菜单文本不应移动。我想使用与当前配置相同的过渡持续时间和计时功能。

不使用 JavaScript/React 是否可行?

【问题讨论】:

  • 添加到菜单:translateY -100%, height: 100vh 并使用过渡(100ms 很好)。这会将菜单置于屏幕上方。添加到menu-openedtranslateY0。希望有帮助!
  • @mikemaccana 这给了我一个幻灯片过渡,而不是擦除。当它进出时,文本也在进出。我想要的是菜单已经处于其最终位置,但过渡到从上到下覆盖主要内容。有点像向下滚动墙纸,我猜?
  • 你是对的,我的错。如果你用这个做一个codesandbox,我会帮你擦。或者,如果您想自己解决,您将通过转换从 width: 0 转到 width : 100vw

标签: javascript html css css-transitions


【解决方案1】:

另一个使用clip-path的想法

let menuOpened = false;

document.getElementById('menu-button')
    .addEventListener('click', function() {
      menuOpened = !menuOpened;
      document.getElementById('body').classList.toggle('menu-opened', menuOpened);
      document.getElementById('menu').classList.toggle('menu-opened', menuOpened);
    });
* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

body.menu-opened {
  overflow-y: hidden;
}

body > * {
  width: 100vw;
}

header {
  background-color: #6FC5C2;
  display: flex;
  height: 20vh;
  position: sticky;
  top: 0;
  
  align-items: center;
  justify-content: center;
}

nav {
  background-color: #80CAF1;
  display: flex;
  height: 80vh;
  left: 0;
  padding: 1rem;
  position: fixed;
  top: 20vh;
  transition: all 0.8s ease;
  z-index: 20;
  
  align-items: center;
  flex-direction: column;
  justify-content: center;
  clip-path:polygon(0 0,0% 0,-200px 100%,0 100%);
}

nav.menu-opened {
  clip-path:polygon(0 0,calc(100% + 200px) 0,100% 100%,0 100%);
}

a {
  color: black;
  font-weight: bold;
  text-decoration: none;
}

a:not(:last-child) {
  margin-bottom: 0.5rem;
}

main {
  display: flex;
}

aside {
  background-color: #9C9ECF;
  display: flex;
  flex-basis: 25%;
  padding: 3rem 0.5rem;
  text-align: center;
  
  justify-content: center;
}

section {
  background-color: #F8CFD7;
  display: flex;
  flex-basis: 75%;
  padding: 2rem;
  
  align-items: stretch;
  flex-direction: column;
}

article {
  border: ridge #80CAF1;
  border-width: 3px 3px 0 3px;
  display: flex;
  font-size: 0.75rem;
  min-height: 15vh;
  padding: 1rem;
  
  align-items: center;
}

article:last-child {
  border-width: 3px;
}

footer {
  background-color: #016CBA;
  height: 30vh;
}
<body id="body">
  <header>
    <button id="menu-button" type="button">Menu</button>
  </header>
  <nav id="menu">
    <a href="/">Link 1</a>
    <a href="/">Link 2</a>
  </nav>
  <main id="main">
    <aside>Filter Form</aside>
    <section>
      <article>Article A</article>
      <article>Article B</article>
      <article>Article C</article>
      <article>Article D</article>
      <article>Article E</article>
      <article>Article F</article>
      <article>Article G</article>
      <article>Article H</article>
      <article>Article I</article>
    </section>
  </main>
  <footer id="footer"></footer>
</body>

【讨论】:

    【解决方案2】:

    现在,您将它与visibility 一起使用是吗? 不要使用它!

    使用height: 0; 然后当你想在 js 中打开它时将其转换为height: 100% 或其他大小。

    并使用transition: height .5s; 作为动画打开。

    【讨论】:

    • 我得到的效果是菜单在打开时会向下增长/拉伸。再次引用 gif 图像,文本不应该移动,菜单应该向下“滚动”以覆盖下面的内容
    • 在span标签中使用你的文本,并使用position: absolute; css样式。
    【解决方案3】:

    折腾后,我终于找到了一个可以达到我想要的效果的解决方案:

    let menuOpened = false;
    
    document.getElementById('menu-button')
        .addEventListener('click', function() {
          menuOpened = !menuOpened;
          document.getElementById('body').classList.toggle('menu-opened', menuOpened);
          document.getElementById('menu').classList.toggle('menu-opened', menuOpened);
        });
    * {
      box-sizing: border-box;
    }
    
    body {
      margin: 0;
      overflow-x: hidden;
    }
    
    body.menu-opened {
      overflow-y: hidden;
    }
    
    body > * {
      width: 100vw;
    }
    
    header {
      background-color: #6FC5C2;
      display: flex;
      height: 20vh;
      position: sticky;
      top: 0;
      
      align-items: center;
      justify-content: center;
    }
    
    nav {
      background-color: #80CAF1;
      clip-path: inset(0 0 80vh);
      display: flex;
      height: 80vh;
      left: 0;
      padding: 1rem;
      position: fixed;
      top: 20vh;
      transition: clip-path 0.35s ease;
      z-index: 20;
      
      align-items: center;
      flex-direction: column;
      justify-content: center;
    }
    
    nav.menu-opened {
      clip-path: inset(0);
    }
    
    a {
      color: black;
      cursor: pointer;
      font-weight: bold;
      text-decoration: none;
    }
    
    a:not(:last-child) {
      margin-bottom: 0.5rem;
    }
    
    main {
      display: flex;
    }
    
    aside {
      background-color: #9C9ECF;
      display: flex;
      flex-basis: 25%;
      padding: 3rem 0.5rem;
      text-align: center;
      
      justify-content: center;
    }
    
    section {
      background-color: #F8CFD7;
      display: flex;
      flex-basis: 75%;
      padding: 2rem;
      
      align-items: stretch;
      flex-direction: column;
    }
    
    article {
      border: ridge #80CAF1;
      border-width: 3px 3px 0 3px;
      display: flex;
      font-size: 0.75rem;
      min-height: 15vh;
      padding: 1rem;
      
      align-items: center;
    }
    
    article:last-child {
      border-width: 3px;
    }
    
    footer {
      background-color: #016CBA;
      height: 30vh;
    }
    <body id="body">
      <header>
        <button id="menu-button" type="button">Menu</button>
      </header>
      <nav id="menu">
        <a>Link 1</a>
        <a>Link 2</a>
      </nav>
      <main id="main">
        <aside>Filter Form</aside>
        <section>
          <article>Article A</article>
          <article>Article B</article>
          <article>Article C</article>
          <article>Article D</article>
          <article>Article E</article>
          <article>Article F</article>
          <article>Article G</article>
          <article>Article H</article>
          <article>Article I</article>
        </section>
      </main>
      <footer id="footer"></footer>
    </body>

    诀窍是使用clip-path 在菜单上创建一个遮罩。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2015-03-10
      • 2015-03-10
      • 2015-06-16
      • 2016-06-13
      • 1970-01-01
      • 2022-07-20
      相关资源
      最近更新 更多