英文:
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 -->
<div class="container">
<div class="inner">
</div>
</div>
<!-- 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: '';
}
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('.container');
const input = document.querySelector('input');
input.addEventListener('input', function() {
container.style.height = this.value + 'px';
});
<!-- 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: '';
}
.inner {
background-image: linear-gradient(green, yellow);
width: 200px;
}
<!-- language: lang-html -->
<input type="range" min="100" max="1000" step="1" value="200">
<div class="container">
<div class="inner option1">
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.
</div>
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论