将HTML元素固定在容器底部,而不会剪切其顶部。

huangapple go评论58阅读模式
英文:

Stick HTML element to bottom of container, without ever clipping its top

问题

以下是您要翻译的部分:

我有一个情况,其中我有一个容器 div 元素,以及在此容器内的内部元素(在这种情况下是一张图片)。我希望出现以下情况:

  • 如果容器 div 的高度高于内部元素,内部元素应放在容器底部。
  • 如果容器 div 的高度低于内部元素,则应将内部元素放在容器顶部,并将底部剪裁。

我所遇到的主要困难是内部元素的高度是可变的。理想情况下,我希望有一个仅使用 CSS 的解决方案(当然,如果使用 JavaScript,会更容易)。

部分解决方案

在内部元素的高度已知并固定的情况下,我已经成功地实现了以下期望结果(CodePen 链接):

.container {
  margin-top: 30px;
  margin-bottom: 30px;
  background-color: red;
  overflow: clip;
  height: 100vh;
  position: relative;
  container-type: size;
}

.inner {
  background-image: linear-gradient(green, yellow);
  height: 400px;
  width: 200px;
}

.option1 {
  position: absolute;
  @container (max-height: 400px) {
    top: 0;
  }
  @container (min-height: 400px) {
    bottom: 0;
  }
}
<div class="container">
  <div class="inner">
  </div>
</div>

我不知道这是否可以为任何解决方案提供有用的起点。通过在 @container 查询中访问当前元素的高度,这可能很容易解决。

英文:

I have a situation where I have a container div element, and an inner element (in this case a picture) within this container. I would like the following to happen:

  • If the container div is taller than the inner element, the inner element should be placed at the bottom of the container.
  • If the container div is smaller than the inner element should instead be placed at the top of the container and the bottom is clipped.

The main difficult I am having is that the inner element's height is variable. Ideally, I would like to have a CSS-only solution (it is significantly easier if using JavaScript of course).

Partial Solution

In cases where the inner element height is known and fixed, I have managed to get the desired outcome with the following (CodePen link):

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

.container {
  margin-top: 30px;
  margin-bottom: 30px;
  background-color: red;
  overflow: clip;
  height: 100vh;
  position: relative;
  container-type: size;
}

.inner {
  background-image: linear-gradient(green, yellow);
  height: 400px;
  width: 200px;
}

.option1 {
  position: absolute;
  @container (max-height: 400px) {
    top: 0;
  }
  @container (min-height: 400px) {
    bottom: 0;
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;inner&quot;&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

I don't know if this can provide a useful starting point for any solutions. This could be quite easily fixed by being access the current element's height in the @container queries.

答案1

得分: 6

使用伪元素并为.container设置flex-direction: column

.container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: clip;
}

.container::before {
  content: '';
}

伪元素::before的高度为0(因为我们没有指定任何高度),因此对用户不可见。然而,如果它有一些高度,我们的布局(不使用display: flex)会如下所示:

┌────────────────────────┐
│        ::before        │
├──────┬─────────────────┤
│      │                 │
│.inner│                 │
│      │                 │
├──────┘                 │
│                        │
└────────────────────────┘

display: flex(将其变成一个flexbox)、flex-direction: column(垂直排列元素)和justify-content: space-between(元素之间最大间距)的组合使两个元素接触到两个相对的边缘:

┌────────────────────────┐
│        ::before        │
├────────────────────────┤
│                        │
├──────┐                 │
│      │                 │
│.inner│                 │
│      │                 │
└──────┴─────────────────┘

如果.container的高度不足以容纳其子元素的高度总和,它将首先尝试缩小其子元素。由于::before从未有过高度,而.inner已经适应了其内容,它们之间的空间会折叠为0,.inner将被裁剪:

┌────────────────────────┐
│        ::before        │
├──────┬─────────────────┤
│      │                 │
│.inner│                 │
└──────┴─────────────────┘

试一下:(以下是代码示例,不需要翻译)

英文:

Simply use a pseudo element and set flex-direction: column for .container:

.container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: clip;
}

.container::before {
  content: &#39;&#39;;
}

The pseudo-element ::before has a height of 0 (since we didn't specify any) so it is invisible to users. If it had some height, however, our layout (without display: flex) would look like this:

┌────────────────────────┐
│        ::before        │
├──────┬─────────────────┤
│      │                 │
│.inner│                 │
│      │                 │
├──────┘                 │
│                        │
└────────────────────────┘

The combo of display: flex (make it a flexbox), flex-direction: column (place elements vertically) and justify-content: space-between (maximum space between elements) makes the two elements touch two opposite sides:

┌────────────────────────┐
│        ::before        │
├────────────────────────┤
│                        │
├──────┐                 │
│      │                 │
│.inner│                 │
│      │                 │
└──────┴─────────────────┘

If .container is not as high as the sum of its children's heights, it will first try to shrink its children. Since ::before never had any height to begin with, and .inner has already fit its content, the space between them collapse to 0 and .inner will be clip-ped:

┌────────────────────────┐
│        ::before        │
├──────┬─────────────────┤
│      │                 │
│.inner│                 │
└──────┴─────────────────┘

Try it:

<!-- begin snippet: js hide: true -->

<!-- language: lang-js -->

const container = document.querySelector(&#39;.container&#39;);
const input = document.querySelector(&#39;input&#39;);

input.addEventListener(&#39;input&#39;, function() {
  container.style.height = this.value + &#39;px&#39;;
});

<!-- language: lang-css -->

.container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  margin: 30px 0;
  background-color: red;
  overflow: clip;
  height: 200px;
}

.container::before {
  content: &#39;&#39;;
}

.inner {
  background-image: linear-gradient(green, yellow);
  width: 200px;
}

<!-- language: lang-html -->

&lt;input type=&quot;range&quot; min=&quot;100&quot; max=&quot;1000&quot; step=&quot;1&quot; value=&quot;200&quot;&gt;

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;inner option1&quot;&gt;
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam interdum purus nec interdum tristique. Maecenas eleifend, libero nec varius cursus, lacus eros elementum odio, eget convallis risus erat ut velit. Pellentesque ut ex lobortis, hendrerit ipsum
    ut, pretium dui. Morbi porta viverra eros eget malesuada. Praesent sed metus eu dui fermentum sagittis. Aliquam blandit ultricies hendrerit. Integer dignissim enim est, id vestibulum ante ultricies eu. Cras at est quis sem luctus finibus. Mauris in
    maximus turpis.
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年4月11日 15:26:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75983400.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定