带有标题的 CSS 可调整大小的图像
Posted
技术标签:
【中文标题】带有标题的 CSS 可调整大小的图像【英文标题】:CSS resizable images with header 【发布时间】:2015-03-05 10:01:27 【问题描述】:我正在尝试获取并排显示的两个图像的 html 布局,并填充页面,同时保持它们的纵横比并保持图像彼此相邻(即不在每一半的中心页)。我还想要顶部的标题。我几乎已经使用下面的 CSS 黑客实现了这一点。目前它看起来像这样:
如果我将其水平缩小,图像会按预期缩小(注意 SO 已使图像适应宽度,但“选择图像。”文本大小实际上是恒定的)。
问题是我的图像填满了整个页面,因为我使用 CSS vw
和 vh
单位(视图宽度和视图高度)。它们允许您将宽度或高度设置为整个视图的百分比,但不能设置封闭 div 的百分比,所以我不能只将它放在一个 div 中(iframe
可以工作,但是呃)。因为我的标题是绝对定位的,所以当我垂直收缩窗口时,它看起来像这样:
我的代码如下。有谁知道如何在不借助 javascript 调整大小的情况下解决此问题?
*
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
body
margin: 20px;
html
background-color: #f4f4f6;
.halfContainer
width: 50vw;
height: 100vh;
margin: auto;
padding: 0;
top: 0;
bottom: 0;
position: absolute;
#leftContainer
left: 0;
#rightContainer
right: 0;
/* AR is height/width. */
#leftImage
/* Set to half width, minus padding. 50-padding = 45 */
width: 45vw;
/* Multiply by aspect ratio. 45 * AR = ... */
/*height: 35vw;*/
/* Clip by height if necessary, minus padding. 100-padding*2 = 90 */
max-height: 90vh;
/* Divide by aspect ratio. 90 / AR = ... */
/*max-width: 140vh; */
margin: auto;
position: absolute;
top: 0;
bottom: 0;
right: 5%; /* Padding */
#rightImage
/* Set to half width, minus padding. 50-padding = 45 */
width: 45vw;
/* Multiply by aspect ratio. 45 * AR = ... */
/*height: 35vw;*/
/* Clip by height if necessary, minus padding. 100-padding*2 = 90 */
max-height: 90vh;
/* Divide by aspect ratio. 90 / AR = ... */
/*max-width: 140vh;*/
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 5%;
#instructions
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<center><h1 id="instructions">Choose an image.</h1></center>
<div id="leftContainer" class="halfContainer">
<img id="leftImage" src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"
style="height: 33.70vw; max-width: 120.15vh;"/>
</div>
<div id="rightContainer" class="halfContainer">
<img id="rightImage" src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"
style="height: 49.41vw; max-width: 81.95vh;"/>
</div>
</body>
</html>
【问题讨论】:
好久没看到<br/>
s! :-)
【参考方案1】:
首先,您可以在图像标签上设置max-width: 100%;
和height: auto;
,而不是对每张图像的高度和最大宽度进行硬编码。
然后您可以在.halfContainer
div 上设置top: 40px;
以使容器开始向下40 像素。
最后,将图像的max-height
设置为calc(100vh - 40px);
,以便它们始终是页眉和页面底部之间的高度。然后top: 0;
和bottom: 0;
将确保图像与容器的顶部和底部正确对齐。
*
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
body
margin: 20px;
html
background-color: #f4f4f6;
.halfContainer
width: 50vw;
margin: auto;
padding: 0;
top: 40px;
bottom: 0;
position: absolute;
#leftContainer
left: 0;
#rightContainer
right: 0;
img
max-width: 100%;
height: auto;
#leftImage
max-height: calc(100vh - 40px);
margin: auto;
position: absolute;
top: 0;
bottom: 0;
right: 5%;
/* Padding */
#rightImage
max-height: calc(100vh - 40px);
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 5%;
#instructions
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
<center>
<h1 id="instructions">Choose an image.</h1>
</center>
<div id="leftContainer" class="halfContainer">
<img id="leftImage" src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg" />
</div>
<div id="rightContainer" class="halfContainer">
<img id="rightImage" src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" />
</div>
【讨论】:
这是最好的答案,因为它仍然使用图像(而不是带有背景图像的 div,这在我的情况下不太理想),并且因为当窗口很大时图像保持相邻。谢谢!【参考方案2】:我重构了您的代码以提出此解决方案。这利用background-image
和background-size
属性来调整图像大小。我还从 vh
和 vw
移开其他元素的大小,但您可以在 .wrapper
中将其更改回来。好处是它是一个纯 CSS 解决方案;没有 JS。稍加修改,它应该可以满足您的需求。如果有任何问题,请告诉我。
* margin:0; padding:0; box-sizing:border-box;
body margin:20px; height:calc(100% - 40px); width:calc(100% - 40px);
html height:100%; width:100%;
.wrapper position:relative; height:100%; width:100%; background-color: #f4f4f6;
.title text-align:center; height:2.4em; overflow:hidden;
.left, .right padding:15px; height:calc( 100% - 2.4em); width:50%; position:absolute;
.left .imgCanvas, .right .imgCanvas width:100%; height:100%; background-repeat:no-repeat; background-size:contain;
.left right:50%;
.left .imgCanvas float:right; background-position:right;
.right left:50%;
.right .imgCanvas float:left; background-position:left;
<div class="wrapper">
<div class="title">
<h1>Choose an image</h1>
</div>
<div class="left">
<div class="imgCanvas" style="background-image:url('http://placekitten.com/g/500/3000')"></div>
</div>
<div class="right">
<div class="imgCanvas" style="background-image:url('http://placekitten.com/g/3000/500')"></div>
</div>
</div>
【讨论】:
效果很好,谢谢!我想我会选择 mikelt21 的解决方案,因为它仍然使用<img>
s。【参考方案3】:
如果您为此使用 background-image
(它适用于 IE9),您可以让自己更好地控制照片的大小调整方式,并使您的 HTML 和 CSS 更简单——方法如下:
第 1 步 - 将其分解为更小的问题
现在您正在尝试定位两个不同的图像,同时考虑到它们的周围环境。让我们通过将您的图像放在<div>
中,将其分解为两个更简单的问题,我将称之为#displayArea
。这样我们就可以分别解决#displayArea
的位置问题和解决图片的位置问题。
所以现在我们正在尝试解决更简单的问题:
-
创建我们的
#displayArea
- 它应该尽可能多地占据屏幕而不覆盖顶部的标题
在#displayArea
内放置两张并排显示的图像,并在保持纵横比的同时填充页面并保持图像彼此相邻
第 2 步 - 制作我们的#displayArea
我们希望#displayArea
占用尽可能多的空间。让我们从宽度开始。在你的css中,你将.halfContainer
设置为50vw
的宽度,但你也将body
设置为20px
的边距——这意味着如果我们将#displayArea
100vw
设为宽,整个页面由于左右边距,最终会变成100vw + 40px
宽。
为了让您以后无需更新其他 css 即可更改页边距,我建议您将 #displayArea
的宽度设置为 100%
以填充所有可用空间。
接下来我们需要设置#displayArea
高度。有很多方法可以做到这一点,但它们都分为两类——一类允许标题具有动态高度,另一类允许标题具有固定高度。我会假设标题的固定高度是可以的,但要知道,如果您希望标题具有动态高度(例如允许其中的文本换行),您将需要不同的解决方案。
如果我们假设一个固定的高度,比如40px
,那么使用 CSS calc()
我们可以将#displayArea
的高度设置为视口的高度减去标题区域再减去正文边距。它看起来像这样:
height: calc(100vh - 40px - 40px) /* 40px header, 40px for 2x20px top/bottom margin */
第 3 步 - 制作两张图片
因为我们已经完成了一些艰苦的工作来设置#displayArea
,所以这一步非常简单。虽然我们当然可以使用您提供的 HTML 来完成这项工作,但我建议您考虑在此项目中使用 background-image
。控制 css 的数量可以让您准确了解背景图像的显示方式可以为您节省大量时间和麻烦 - 例如,当这些图像由于浏览器窗口缩小而变小时,您是希望它们垂直居中还是始终为尽可能高?使用 css background-image 很容易做到。
在下面的代码中,我使用了 .half
类,因此图像 div 可以共享样式。然后,我使用他们的唯一 ID 来设置我希望他们每个人拥有的特定图像。
这是完成的 CSS 和 HTML(注意 HTML 现在是多么简单)。
*
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
body
margin: 20px;
html
background-color: #f4f4f6;
#instructions
height: 40px;
#displayArea
height: calc(100vh - 40px - 40px); /* 40px header, 40px for 2x20px top/bottom margin */
width: 100%;
margin: 0;
padding: 0;
.half
float: left;
width: 50%;
margin: 0;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: center top;
#leftImg
background-image: url(http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg);
background-position: right top;
#rightImg
background-image: url(http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg);
background-position: left top;
<center><h1 id="instructions">Choose an image.</h1></center>
<div id="displayArea">
<div id="leftImg" class="half"></div>
<div id="rightImg" class="half"></div>
</div>
【讨论】:
几乎,但是图像在页面的每一半中居中,这不是我想要的。无论如何,谢谢! @Timmmm - 我更改了 CSS 以展示如何将图像定位为彼此相邻 - 背景位置具有很大的灵活性:CSS :-)跨度> 【参考方案4】:我知道你已经选择了一个答案,但我还是想给你这个选项。
因为您正在使用 vh
和 vw
测量值,但没有定义标题高度,如果不使用 JavaScript 动态检测标题的大小以调整列的大小,您目前要求做的事情是不可能的。到那时,您还不如只使用 JavaScript 来处理它而忘记视口单位。
话虽如此,这里有一个 JavaScript 解决方案,我相信它会按照您想要的方式呈现内容:
window.onload = function()
window.left = document.getElementById("leftImage"),
window.right = document.getElementById("rightImage"),
window.head = document.getElementById("instructions"),
window.leftW = parseInt(window.getComputedStyle(left, null).getPropertyValue('width')),
window.rightW = parseInt(window.getComputedStyle(right, null).getPropertyValue('width')),
window.leftH = parseInt(window.getComputedStyle(left, null).getPropertyValue('height')),
window.rightH = parseInt(window.getComputedStyle(right, null).getPropertyValue('height'));
console.log(leftW);
resize(leftW, rightW, leftH, rightH);
window.onresize = function()
resize(leftW, rightW, leftH, rightH);
function resize(leftW, rightW, leftH, rightH)
var winW = window.innerWidth,
hcPadW = (winW * .025 * 2),
winH = window.innerHeight,
hcPadH = (winH * .025 * 2),
colW = (winW / 2),
colH = (winH - parseInt(window.getComputedStyle(head, null).getPropertyValue('height'))),
colR = ((colW - hcPadW) / (colH - hcPadH)),
leftR = (leftW / leftH),
rightR = (rightW / rightH);
if(colR < leftR)
left.style.width = (colW - hcPadW) + 'px';
left.style.height = (((colW - hcPadW) * leftH) / leftW) + 'px';
else
left.style.height = (colH - hcPadH) + 'px';
left.style.width = (((colH - hcPadH) * leftW) / leftH) + 'px';
if(colR < rightR)
right.style.width = (colW - hcPadW) + 'px';
right.style.height = (((colW - hcPadW) * rightH) / rightW) + 'px';
else
right.style.height = (colH - hcPadH) + 'px';
right.style.width = (((colH - hcPadH) * rightW) / rightH) + 'px';
*
margin: 0;
padding: 0;
html, body
height: 100vh;
#wrapper
height: 100vh;
background-color: #dedede;
display: table;
#instructions, .hidden
display: table-row;
.hidden
visibility: hidden;
#instructions
text-align: center;
background-color: #9a9a9a;
position: absolute;
top: 0;
left: 0;
right: 0;
#cols
display: table-row;
.halfContainer
display: table-cell;
width: 50vw;
height: 100%;
padding: 2.5vh 2.5vw;
vertical-align: middle;
#leftContainer
background-color: #797979;
text-align: right;
<div id="wrapper">
<div class="hidden"><h1>Choose an image.</h1></div>
<div id="instructions"><h1>Choose an image.</h1></div>
<div id="cols">
<div id="leftContainer" class="halfContainer"><img id="leftImage" src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg" class="image" /></div><div id="rightContainer" class="halfContainer"><img id="rightImage" src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" class="image" /></div>
</div>
</div>
JSFiddle:http://jsfiddle.net/rLuf9zso/
下面是更简化的路由,将 JavaScript 最小化到绝对最小值:
window.onload = function()
var mH = document.getElementsByClassName('image');
for(var i = 0; i < mH.length; i++)
mH[i].style['maxHeight'] = 'calc(94vh - ' + parseInt(window.getComputedStyle(document.getElementById('instructions'), null).getPropertyValue('height')) + 'px)';
*
margin: 0;
padding: 0;
html, body
height: 100vh;
#wrapper
height: 100vh;
display: table;
#instructions, .hidden
display: table-row;
.hidden
visibility: hidden;
#instructions
text-align: center;
position: absolute;
top: 0;
left: 0;
right: 0;
#cols
display: table-row;
.halfContainer
display: table-cell;
width: 50vw;
height: 100%;
padding: 2.5vh 2.5vw;
vertical-align: middle;
#leftContainer
text-align: right;
.image
min-height: 0;
min-width: 0;
max-width: 40vw;
margin: auto;
<div id="wrapper">
<div class="hidden"><h1>Choose an image.</h1></div>
<div id="instructions"><h1>Choose an image.</h1></div>
<div id="cols">
<div id="leftContainer" class="halfContainer"><img id="leftImage" src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg" class="image" /></div><div id="rightContainer" class="halfContainer"><img id="rightImage" src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" class="image" /></div>
</div>
</div>
JSFiddle:http://jsfiddle.net/18ynkzd0/
两者之间的主要区别在于兼容性。第一个具有更广泛的 JavaScript,将在大多数主要浏览器中兼容,可以追溯到几个版本,而第二个遵循您最初的方案,忽略 IE 8/9 和 android 4.1/.3 等浏览器。
关于这些选项要记住的其他一点是,标题的高度可以从div#instructions
检索,但图像上的定位不受它的影响。由于标头已定位,因此它的高度不会影响图像位置的渲染。作为补偿,我添加了具有相同值/CSS 的div#hidden
,并将其可见性设置为隐藏。这将添加内联所需的高度而不显示它。如果您更改显示的标题,请确保更新隐藏的div
以匹配。
我希望这会有所帮助。 ^^
【讨论】:
非常感谢!这绝对有用。 我很高兴我能提供帮助,即使它只是提供了一些知识。 ^^【参考方案5】:好的,现在答案略有不同。我在您的代码中添加了以下内容:
@media (max-height: 500px)
.halfContainer
top: 100px;
overflow: auto;
一旦屏幕高度低于 200 像素,这将下推图像。自动溢出将不允许滚动。您可能会看到更少的图像。
*
margin: 0;
padding: 0;
/* Fix CSS. */
box-sizing: border-box;
body
margin: 20px;
html
background-color: #f4f4f6;
.halfContainer
width: 50vw;
height: 100vh;
margin: auto;
padding: 0;
top: 0;
bottom: 0;
position: absolute;
@media (max-height: 500px)
.halfContainer
top: 100px;
overflow: auto;
#leftContainer
left: 0;
#rightContainer
right: 0;
/* AR is height/width. */
#leftImage
/* Set to half width, minus padding. 50-padding = 45 */
width: 45vw;
/* Multiply by aspect ratio. 45 * AR = ... */
/*height: 35vw;*/
/* Clip by height if necessary, minus padding. 100-padding*2 = 90 */
max-height: 90vh;
/* Divide by aspect ratio. 90 / AR = ... */
/*max-width: 140vh; */
margin: auto;
position: absolute;
top: 0;
bottom: 0;
right: 5%; /* Padding */
#rightImage
/* Set to half width, minus padding. 50-padding = 45 */
width: 45vw;
/* Multiply by aspect ratio. 45 * AR = ... */
/*height: 35vw;*/
/* Clip by height if necessary, minus padding. 100-padding*2 = 90 */
max-height: 90vh;
/* Divide by aspect ratio. 90 / AR = ... */
/*max-width: 140vh;*/
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 5%;
#instructions
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<center><h1 id="instructions">Choose an image.</h1></center>
<div id="leftContainer" class="halfContainer">
<img id="leftImage" src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"
style="height: 33.70vw; max-width: 120.15vh;"/>
</div>
<div id="rightContainer" class="halfContainer">
<img id="rightImage" src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"
style="height: 49.41vw; max-width: 81.95vh;"/>
</div>
</body>
</html>
【讨论】:
几乎!但是图像现在从页面底部消失了。 用@media
查询编辑了我的答案。希望这会有所帮助。
还是不行。不过还是谢谢!看来我得用javascript了。【参考方案6】:
这可能是一个 hack,但您可以在标题下方放置一个 <div style="height:50px"></div>
。
您必须将高度替换为标题的高度。
【讨论】:
我认为他发布了一个被富文本编辑器删除的 HTML 标签【参考方案7】:.halfContainer
float:left;
margin: 10px;
overflow: hidden;
height: 150px;
.halfContainer img
max-width: 100%; max-height: 100%;
<!DOCTYPE html>
<html lang="en">
<head>
<title> test </title>
<meta charset="">
</head>
<body>
<center><h1 id="instructions">Choose an image.</h1></center>
<div class="halfContainer">
<img src="http://www.washingtonpost.com/news/morning-mix/wp-content/uploads/sites/21/2014/09/Grumpy_Cat_Endorsement-017d7-ULFU.jpg"/>
</div>
<div class="halfContainer">
<img src="http://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg"/>
</div>
</body>
</html>
【讨论】:
以上是关于带有标题的 CSS 可调整大小的图像的主要内容,如果未能解决你的问题,请参考以下文章