CSS 可调整大小的图片 header

CSS resizable images with header

我正在尝试获取显示 side-by-side 的两张图片的 HTML 布局,并在保持纵横比并保持图片彼此相邻的同时填充页面(即不在页面的每一半的中心)。我还想要一个 header 在顶部。我几乎已经使用下面的 CSS hackery 实现了这一点。目前看起来像这样:

如果我水平缩小它,图像会按预期缩小(注意 SO 已使图像适合宽度,但 "Choose an image." 文本大小实际上是恒定的)。

问题是我的图片占满了整个页面,因为我使用的是 CSS vwvh 单位(视图宽度和视图高度)。它们允许您将宽度或高度设置为整个视图的百分比,而不是封闭 div 的百分比,所以我不能只将它放在 div 中(iframe 会起作用但是呃)。因为我的 header 是绝对定位的,当我垂直收缩 window 时它看起来像这样:

我的代码如下。有谁知道如何在不诉诸 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>

这可能是一个 hack,但您可以在 header 下方放置一个 <div style="height:50px"></div>

您必须将高度替换为 header 的高度。

好的,现在答案略有不同。我在您的代码中添加了以下内容:

@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>

我重构了您的代码以得出此解决方案。这利用 background-imagebackground-size 属性来调整图像的大小。我也放弃了 vhvw 来调整其他元素的大小,但您可以在 .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>

首先,您可以在图片标签上设置 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>

如果为此使用 background-image,您可以更好地控制照片的大小调整方式,并使 HTML 和 CSS 变得更简单(在 IE9 中有效) ) – 方法如下:

第 1 步 - 将其分解为更小的问题

现在您正在尝试定位两个不同的图像,同时考虑到它们的周围环境。让我们把你的图像放在我称之为 #displayArea<div> 中,将其分解为两个更简单的问题。这样我们就可以解决 #displayArea 的放置问题,而不是解决图像的放置问题。

所以现在我们正在尝试解决更简单的问题:

  1. 制作我们的 #displayArea - 它应该尽可能多地占据屏幕,而不会覆盖顶部的 header
  2. #displayArea 中放置两张显示的图像 side-by-side,并在保持宽高比并保持图像彼此相邻的同时填充页面

第 2 步 - 让我们的 #displayArea

我们希望 #displayArea 占用尽可能多的 space。让我们从宽度开始。在您的 css 中,您将 .halfContainer 的宽度设置为 50vw,但您还将 body 的边距设置为 20px - 这意味着如果我们我们的 #displayArea 100vw 宽,由于左右页边距,整个页面最终会变成 100vw + 40px 宽。

为了让您以后可以更改页边距而无需更新其他 css,我建议您 #displayArea 通过设置填充所有可用的 space它的宽度为 100%.

接下来我们需要设置#displayArea高度。有很多方法可以做到这一点,但它们都分为两类 - 允许 header 具有动态高度的一类,以及具有固定高度的一类。我假设 header 的固定高度是可以的,但是如果您希望 header 具有动态高度(例如允许其中的文本换行)。

如果我们假设一个固定的高度,比方说 40px,那么使用 CSS calc() 我们可以将 #displayArea 的高度设置为视口减去 header 区域并减去 body 边距。它看起来像这样:

height: calc(100vh - 40px - 40px) /* 40px header, 40px for 2x20px top/bottom margin */

第 3 步 - 制作两张图片

因为我们已经完成了一些艰苦的设置工作 #displayArea,所以这一步非常简单。虽然我们当然可以使用您提供的 HTML 来完成这项工作,但我还是建议您考虑在此项目中使用 background-image。控制量 css 让您准确了解背景图像的显示方式,可以为您节省大量时间和麻烦 - 例如,当这些图像由于浏览器 window 缩小而变小时,您是否想要它们垂直居中,还是总是尽可能高? css background-image.

很容易做到

在我下面的代码中,我使用了 class .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>

.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>

我知道你已经选择了一个答案,但我还是想给你这个选项。

因为您正在使用 vhvw 测量但没有定义 header 高度,如果不使用 JavaScript动态检测 header 的大小以调整列的大小。到那时,您不妨只使用 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.

关于这些选项还有一点要记住,header 的高度可以从 div#instructions 中获取,但图像上的定位不受它的影响。由于 header 已定位,因此它的高度不会影响图像位置的渲染。作为补偿,我添加了具有相同 values/CSS 的 div#hidden 并将其可见性设置为隐藏。这将添加内联所需的高度而不显示它。如果您更改显示的 header,请确保更新隐藏的 div 以匹配。

希望对您有所帮助。 ^^