我必须解决同样的任务。我必须放置几个具有不同纵横比的图像来填充页面(或容器)的宽度。
我希望它们都具有相同的高度:
TL;TR
我为此任务找到了 2 个纯 CSS 解决方案:
- 基于填充和边距属性行为,以使元素的纵横比保持恒定
来源:https://wellcaffeinated.net/articles/2012/12/10/very-simple-css-only-proportional-resizing-of-elements
将元素的宽度定义为元素的百分比(例如:100%)
parent 的宽度,然后将元素的 padding-top(或 -bottom)定义为
一个百分比,以便高度是您需要的纵横比。
- 使用 flexbox 响应等高图像保留图像的纵横比
来源:https://codepen.io/blimpage/pen/obWdgp
将每个图像的包装 div 的 flex 属性设置为图像的
纵横比(宽度除以高度)
两种解决方案都假定您需要知道图像的大小才能构建正确的 CSS。
您可以使用服务器端脚本,例如PHP为此。
有用于此的函数或库。
例如,PHP 有一个 getimagesize() 函数。 (见https://www.php.net/manual/ru/function.getimagesize.php)
如果只需要放置几张图像,您可以查找那里的大小并将其硬编码到 PHP 脚本中,从而输出生成的 HTML。
为简单起见,我将使用此方法。
另一种方法是在 CSS 中使用 calc() 函数。
详情
解决方案 1. 带有 padding 属性的纯 CSS
下面的一些解释。
变量说明:
- W - 是页面/容器宽度。
- H - 是具有图像宽度的块。任何图像都一样。
- w0[i], h0[i] - 是第 i 个图像的原始尺寸。
- w[i], h[i] - 显示第 i 个图像的大小。
- h[i]=H
让我们计算比率
W=SUM(w[i]),因为图像填满了宽度。
让我们将它除以 H=h[i]:
W/H=SUM(w[i]/h[i])
让我们计算 i 图像的纵横比
r[i]=w[i]/h[i]=w0[i]/h0[i],因为它必须是该图像的常数
所以我们得到
W/H=SUM(r[i])
或 H=W/SUM(r[i])
这是整个容器的纵横比:
R=W/H=SUM(r[i])
所以我们可以得到 H=W/R
PHP 代码示例:
<?php
//Image sizes
$arImages = [
['NAME' => '11.png', 'W' => 1000, 'H' => 1000],
['NAME' => '12.png', 'W' => 1000, 'H' => 2000],
['NAME' => '21.png', 'W' => 2000, 'H' => 1000],
];
?>
<!DOCTYPE html>
<html>
<head>
<?php
$r = 0;
//Loop through all images
foreach ($arImages as $image) {
$w = $image['W'];
$h = $image['H'];
$r += $w / $h;
} ///Loop through all images
//The band height as a percentage of the window width
$hBand = (1 / $r) * 100;
?>
<style>
.page {
width: 100%;
}
.sh-band {
border: 1px solid blue;
padding: 0;
}
.sh-band-resizer {
width: 100%;
padding-top: <?= $hBand ?>%;
position: relative;
}
.sh-element {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.sh-element img {
width: auto;
height: 100%;
}
</style>
</head>
<body>
<div class="page">
<?
/**
* Proportional scaling with padding-top CSS
*/
?>
<div class="sh-band" style="">
<div class="sh-band-resizer">
<div class="sh-element"><?php
//Loop through all images
foreach ($arImages as $image) {
?><img src="/sh-gallery/images/<?= $image['NAME'] ?>"><?php
} // /Loop through all images
?></div>
</div>
</div>
</div>
</body>
</html>
HTML + CSS,由@s-j 答案中的示例图像代码生成:
<html><head>
<style>
.page {
width: 100%;
}
.sh-band {
border: 1px solid blue;
padding: 0;
}
.sh-band-resizer {
width: 100%;
padding-top: 48.191461696405%;
position: relative;
}
.sh-element {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.sh-element img {
width: auto;
height: 100%;
}
</style>
</head>
<body>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="col-9">
<div class="page">
<div class="sh-band" style="">
<div class="sh-band-resizer">
<div class="sh-element"><img src="https://i.stack.imgur.com/tDEmT.jpg"><img src="https://i.stack.imgur.com/WSp0o.jpg"></div>
</div>
</div>
</div>
</div>
</body></html>
解决方案 2. 弹性盒变体
您仍然需要知道服务器端的图像大小才能构建内联 CSS。
关键思想是将每个图像的包装器 div 的 flex 属性设置为图像的纵横比,即它的宽度除以它的高度。
如果您只指定 1 个参数给 flex 属性,则被解释为 flex: 1 0; (见https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
所以 flex-grow 将被设置为图像的 aspect,flex-shrink 为 1,flex-basis 为 0;
(参见The difference between flex-basis auto and 0 (zero) 关于“零”弹性基础)
首先,它将图像缩小到最小尺寸(零),然后根据它们的纵横比拉伸它们的宽度以实现完整的 flex 容器宽度。
解释。
变量说明:
- W - 是页面/容器宽度。
- H - 是具有图像宽度的块。任何图像都一样。
- w0[i], h0[i] - 是第 i 个图像的原始尺寸。
- w[i], h[i] - 显示第 i 个图像的大小。
- r[i]=w0[i]/h0[i]=w[i]/h[i] - 图像的纵横比
- h[i]=H - 图片的高度必须相同
要确定特定图像的实际宽度,我们必须将所有 flex-grow 因素相加。
R=SUM(r[i])
然后我们可以计算一个单独的宽度并使用我们得到的恒定纵横比
w[i]=r[i]*W/R=(w[i]/h[i])*W/R
因此
h[i]=W/R
我们可以看到 h[i] 对于所有图像都是常数,仅取决于 W/R。
此外,我们通过设置自动 img 高度属性来使用图像纵横比保存。
(见https://css-tricks.com/flex-grow-is-weird/)
一个 PHP 示例:
<?php
//Image sizes
$arImages = [
['NAME' => '11.png', 'W' => 1000, 'H' => 1000],
['NAME' => '12.png', 'W' => 1000, 'H' => 2000],
['NAME' => '21.png', 'W' => 2000, 'H' => 1000],
];
?>
<!DOCTYPE html>
<html>
<head>
<style>
.page {
width: 100%;
}
.sh-band {
border: 1px solid blue;
display: flex;
}
.sh-element img {
width: 100%;
height: auto;
vertical-align: middle;
}
</style>
</head>
<body>
<div class="page">
<?
/**
* Proportional scaling with flex
*/
?>
<div class="sh-band">
<?php
//Loop through all images
foreach ($arImages as $image) {
?>
<div class="sh-element" style="flex: <?= $image['W'] / $image['H'] ?>">
<img src="/sh-gallery/images/<?= $image['NAME'] ?>">
</div>
<?php
} // /Loop through all images
?>
</div>
</div>
</body>
</html>
一个引导结果代码:
.page {
width: 100%;
}
.sh-band {
border: 1px solid blue;
display: flex;
}
.sh-element img {
width: 100%;
height: auto;
vertical-align: middle;
}
<html>
<head>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
</head>
<body>
<div class="col-9">
<div class="page">
<div class="sh-band">
<div class="sh-element" style="flex: 1.319587628866">
<img src="https://i.stack.imgur.com/tDEmT.jpg">
</div>
<div class="sh-element" style="flex: 0.75546875">
<img src="https://i.stack.imgur.com/WSp0o.jpg">
</div>
</div>
</div>
</div>
</body>
</html>