首页 > 解决方案 > 父级高度根据仅使用 CSS 的可见子级高度而变化

问题描述

我有这样的结构:

<div class="body">
  <div class="wrapper">
    <div class="dialog">
      <div class="content-0"></div>
      <div class="content-1"></div>
      <div class="content-2"></div>
    </div>
  </div>
</div>

父元素 .dialog 包含三个水平对齐的内容项。可见仅是活动的 .content-*。其他内容项被隐藏。当用户单击按钮时,活动项目向左滑动到隐藏区域,下一个项目变为活动且可见这里是演示行为的小提琴:https ://jsfiddle.net/fmbn28xs/

我的问题是-每次用户单击按钮时,如何仅使用CSS根据可见内容(.content-*)项目高度调整父级(.dialog)高度,这可能吗?

更新:内容项的高度事先不知道。

标签: javascripthtmlcss

解决方案


您可以使用自定义 css 属性(全页预览)来做到这一点:

var index = 0;
function slide() {
  index++;
  var current = index % 3;
  var target = document.querySelector(`.dialog`);
  target.style.setProperty('--index', current);
}
.body {
  background-color: #fff;
  width: 100%;
  height: 100%;
  position: relative;
}

.wrapper {
  background-color: grey;
  position: absolute;
  top: 50%;
  right: 50%;
  transform: translate(50%, 20%);
  overflow: hidden;
}

.dialog {
  --index: 0;
  width: 300px;
  display: flex;
  height: calc(200px + 50px * var(--index));
  transition: transform 400ms, height 400ms;
  transform: translateX(calc(var(--index) * -100%));
}
.content-0, .content-1, .content-2 {
  width: 300px;
  flex: 0 0 100%;
  position: relative;
}

.content-0 {
  background-color: tomato;
  height: calc(200px + 50px * 0);
}

.content-1 {
  background-color: yellow;
  height: calc(200px + 50px * 1);
}

.content-2 {
  background-color: green;
  height: calc(200px + 50px * 2);
}

button {
  position: relative;
}
<div class="body">
  <div class="wrapper">
    <div class="dialog">
      <div class="content-0"></div>
      <div class="content-1"></div>
      <div class="content-2"></div>
    </div>
    <button onclick="slide()">Next</button>
  </div>
</div>

但是您必须手动为所有内容分配高度。

如果您使用的是预编译 css 库(例如 scss),您还可以自动执行此操作:

.dialog > *{
  @for $i from 1 through 3 {
    &:nth-child(#{$i}) {
      height: calc(200px + 50px * #{$i});
    }
  }
}

更新

如果高度是动态的,您可以使用与从到animation交替相关的技巧来使容器高度相应地适应,但是这样您就不能为高度变化设置动画,因为高度是由其子项的高度决定的。positionrelativeabsolute

var index = 0;
function slide() {
  index++;
  var current = index % 3;
  var target = document.querySelector(`.dialog`);
  target.style.setProperty('--index', current);
  target.setAttribute('data-index', current);
}
.body {
  background-color: #fff;
  width: 100%;
  height: 100%;
  position: relative;
}

.wrapper {
  background-color: grey;
  position: absolute;
  top: 50%;
  right: 50%;
  transform: translate(50%, 20%);
  overflow: hidden;
}

.dialog {
  --index: 0;
  width: 300px;
  position: relative;
}

.dialog > * {
  width: 300px;
  position: absolute;
  z-index: 0;
  animation: popout 400ms both;
  top: 0;
}

.dialog[data-index='0'] > *:nth-child(1), 
.dialog[data-index='1'] > *:nth-child(2), 
.dialog[data-index='2'] > *:nth-child(3) {
  position: relative;
  z-index: 1;
  animation: popin 400ms both;
}

.content-0 {
  background-color: tomato;
  height: 200px;
}

.content-1 {
  background-color: yellow;
  height: 250px;
}

.content-2 {
  background-color: green;
  height: 300px;
}

button {
  position: relative;
}

@keyframes popin {
  from {
    transform: translateX(100%);
  }
  
  to {
    transform: translateX(0);
  }
}

@keyframes popout {
  from {
    transform: translateX(0);
  }
  
  to {
    transform: translateX(-100%);
  }
}
<div class="body">
  <div class="wrapper">
    <div class="dialog" data-index="0">
      <div class="content-0"></div>
      <div class="content-1"></div>
      <div class="content-2"></div>
    </div>
    <button onclick="slide()">Next</button>
  </div>
</div>


推荐阅读