元素在体内找不到足够的空间 - JavaScript样式

时间:2015-11-27 20:40:05

标签: javascript html css responsive-design

相关信息:

该页面包含两个元素:

  • 左侧<aside>

  • 右侧<main>

注意:在本文中,为了完整起见,提到了高度,但与产生此问题无关。)

相对于var w = screen.width/100;(和var h = screen.height/100;)设置所有高度,宽度和边距,以便页面在任何显示分辨率中看起来基本相同。并且设置它们以使<aside><main>的宽度以及它们之间的边距加起来为screen.width

例如:

var w = screen.width/100;
document.getElementsByTagName('main')[0].style.width = 85.5*w + "px";
document.getElementsByTagName('aside')[0].style.width = 14*w + "px";
document.getElementsByTagName('aside')[0].style.marginRight = 0.5*w + "px";

(85.5 + 14 + 0.5 = 100)

问题:

由于未知原因,<main>被推下<aside>以下。我只能想到一个半合理的假设来解释这种行为。

但是,如果我将正文的字体大小设置为0并缩小(以便元素占用更少的空间)并放大,则会得到修复(我不知道为什么,并且不要&#39问我怎么发现这个。)

这种行为的原因是什么,以及正确的解决方法是什么?

假设(可以跳过):

  

浏览器似乎认为&#34;如果我显示滚动条即使不需要它们会发生什么?&#34; ,然后注意到滚动条的宽度大于&gt; 0,这意味着<aside><main>占用的空间比可用空间多(因为它们设置为占据屏幕宽度的100%,现在有一个滚动条竞争空间)。因此,浏览器决定重新定位<main>下面的<aside> 并破坏设计。

现在,<main>位于<aside>以下,元素不再适合屏幕,现在实际需要滚动条,因此保持,甚至虽然它们是他们自己存在的原因(就这个假设而言)。

其他信息:

  • 我没有使用任何CSS样式表:我的所有样式都是通过JavaScript完成的(原因很简单,我希望大小取决于screen.widthscreen.height)。

  • 元素有display = "inline-block";。当浏览器不是最大尺寸时,使用float会产生可怕的行为。

以下是重现问题的代码:

<!DOCTYPE html>
<html>    
<body> 

<aside></aside>

<main></main> 

<script>
  var h = screen.height/100;
  var w = screen.width/100;

  var e = document.getElementsByTagName("aside")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "lightblue";
  e.width = 14*w + "px";
  e.height = 69*h + "px";
  e.marginRight = 0.5*w + "px";

  e = document.getElementsByTagName("main")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "green";
  e.width = 85.5*w + "px";
  e.height = 69*h + "px";   

  e = document.getElementsByTagName("body")[0].style;
  e.margin = e.padding = "0";
  e.backgroundColor = "black";
</script>
</body>
</html>

7 个答案:

答案 0 :(得分:6)

问题编辑后更新

你的mainaside下推的原因是因为你有一个不可见的空间,在你的情况下是换行符,但也可以是一个简单的空格,在你的元素之间标记,它实际上增加了大小以及使它们都超过100%宽度的元素,因此创建了滚动条。

在计算宽度以适合父母宽度时,需要将内联元素(未定位,绝对或固定或浮动)的空间与元素大小一起考虑(在这种情况下)身体/视口)。

在这里你可以阅读更多关于它以及如何摆脱它或使它变成0(如果要保持元素内联)。

并排排列元素的其他方法是使用display: flexdisplay: table-cell,两者都具有与内联元素类似的行为(在与块元素相反的方向上堆叠水平,它堆叠垂直),但与实际尺寸相比,它的设置尺寸不会以相同的方式受到白色空间的影响。

为了澄清,即如果在flex项目上将宽度设置为14.5%,则需要14.5%而不是更多,与内联相反,这将是14.5%加上空白区域(实际上是空格大小)取决于设置的字体大小)

示例display: flex(推荐)

* {
  box-sizing: border-box;
}
html, body {
  margin: 0;
  height: 100%;
}

body {
  display: flex;
  height: 100%;
}
aside {
  width: 14%;
  margin-right: 0.5%;
  background-color: #f66;
}
main {
  width: 85.5%;  
  background-color: #66f;
}
<aside>
  aside
</aside>
<main>
  main
</main>

示例display: table-cell(适用于较旧的浏览器)

* {
  box-sizing: border-box;
}
html, body {
  margin: 0;
  height: 100%;
}

body {
  display: table;
  width: 100%;
  height: 100%;
}
aside {
  display: table-cell;
  width: 14%;
  background-color: #f66;
}
main {
  display: table-cell;
  width: 85.5%;
  background-color: #66f;
}
.margin {
  display: table-cell;
  width: 0.5%;
}
<aside>
  aside
</aside>

<div class="margin"></div>

<main>
  main
</main>

注意:

使用aside时在maindisplay: table之间创建边距的其他方法是使用单元格填充,边框宽度等。

使用现有代码,并且由于不使用普通流程,绝对定位可能是一种选择。

<!DOCTYPE html>
<html>    
<body> 

<aside></aside>

<main></main> 

<script>
  var h = screen.height/100;
  var w = screen.width/100;

  var e = document.getElementsByTagName("aside")[0].style;
  e.position = "absolute";                                     /*  changed  */
  e.backgroundColor = "lightblue";
  e.width = 14*w + "px";
  e.height = 69*h + "px";
  e.marginRight = 0.5*w + "px";

  e = document.getElementsByTagName("main")[0].style;
  e.position = "absolute";                                     /*  changed  */
  e.backgroundColor = "green";
  e.width = 85.5*w + "px";
  e.height = 69*h + "px";   
  e.left = 14.5*w + "px";                                      /*  added  */
  
  e = document.getElementsByTagName("body")[0].style;
  e.margin = e.padding = "0";
  e.backgroundColor = "black";
  
</script>
</body>
</html>

更新2

代码的问题是它在DOM完成之前运行,因此创建滚动条。尝试下面的示例,我添加了一个延迟,你会发现它有效(当浏览器运行最大化时)。

<!DOCTYPE html>
<html>
<script>

  function runOnLoad() {

  setTimeout(function() {

  var h = screen.height/100;
  var w = screen.width/100;

  var e = document.getElementsByTagName("aside")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "lightblue";
  e.width = 14*w + "px";
  e.height = 69*h + "px";
  e.marginRight = 0.5*w + "px";

  e = document.getElementsByTagName("main")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "green";
  e.width = 85.5*w + "px";
  e.height = 69*h + "px";   

  e = document.getElementsByTagName("body")[0].style;
  e.margin = e.padding = "0";
  e.backgroundColor = "black";
  e.fontSize = "0";

  }, 200)

  }
</script>

<body onload="runOnLoad();"> 

<aside></aside>

<main></main> 

</body>
</html>

答案 1 :(得分:3)

滚动条假设是对的。以下是解决方案:How to get screen width without (minus) scrollbar?。我测试了它并使用document.body.clientWidth解决了这个问题。另一个问题是内联块元素需要链接在一起,没有空格或换行符(以避免不必要的边距)。

<body><aside></aside><main></main></body>

答案 2 :(得分:2)

问题是asidemain之间的空白区域占用了一些空间,因为您使用inline-block进行显示。

@Shah Abaz Khan的答案是对的,你必须摆脱这个空白区域。

这可以通过删除它来完成,如建议:

<aside></aside><main></main> 

但是你想保留你的html缩进,你也可以使用html评论<!-- -->

<aside>
    //stuff
</aside><!--

--><main>
    //other stuff
</main>

答案 3 :(得分:1)

几乎完整的解释:

以下作品(但还有其他方法):

  • 将正文的字体大小更改为0,以便内联块元素之间的空格变为0(或使用任何其他技术)。这在其他答案中有详尽解释。

  • 给身体一个固定的宽度。在这种情况下screen.width。之所以能起作用的原因有点复杂。 请注意,如果未指定,正文将占据浏览器(不一定是屏幕)的整个宽度。有两种情况:

    • 警告: 此部分更接近假设而非正确答案。)当浏览器最大化时(屏幕和浏览器的宽度均为相同的)主体的最大宽度为screen.width(如果需要),因此元素占用太多空间。然而,由于身体不会立即知道它需要多宽,它似乎没有“准备好”,所以元素最终会占用太多空间。这就是为什么事先给身体宽度来解决这个问题(还有其他方法可以解决这个问题 - 见其他答案)。

    • 当浏览器最大化时,正文的最大宽度是浏览器窗口的宽度,而不是屏幕的宽度。元素的组合宽度现在大于身体的宽度,因此这种行为。赋予身体固定宽度screen.width可以解决这个问题,但也有其他解决办法(例如将白色空间设置为无包裹)。

以下是建议更改后的代码:

<!DOCTYPE html>
<html>    
<body> 

<aside></aside>

<main></main> 

<script>
  var h = screen.height/100;
  var w = screen.width/100;

  var e = document.getElementsByTagName("aside")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "lightblue";
  e.width = 14*w + "px";
  e.height = 69*h + "px";
  e.marginRight = 0.5*w + "px";

  e = document.getElementsByTagName("main")[0].style;
  e.display = "inline-block";
  e.backgroundColor = "green";
  e.width = 85.5*w + "px";
  e.height = 69*h + "px";   

  e = document.getElementsByTagName("body")[0].style;
  e.margin = e.padding = "0";
  e.backgroundColor = "black";
  e.fontSize = "0";            //this line
  e.width = 100*w + "px";      //and this line have been added
</script>
</body>
</html>

答案 4 :(得分:1)

  

我没有使用任何CSS样式表:我的所有样式都是由JavaScript完成的(原因很简单,我希望大小依赖于screen.width和screen.height)。

     

元素有display =&#34; inline-block&#34;;

你应该知道这是你正在处理的特殊单位:

  • vh:viewport height
  • vw:viewport width

实施例

注意:您可以忽略&#34; Visual Stuff&#34;

&#13;
&#13;
/* VISUAL STUFF */

aside {
  background-color: hsl(0, 85%, 65%);
}
main {
  background-color: hsl(180, 85%, 65%);
}

/* SIZING STUFF */

body {
  /* I guess you don't need it */
  margin: 0;
  /* prevent white space display */
  font-size: 0;
  /* better keep*/
  white-space: nowrap;
}

aside,main {
  /* your constraint */
  display: inline-block;
  /* Set font size back to normal */
  font-size: initial;
  /* if you want the height to fit sreen */
  /* this means "height = 100% of viewport's height" */
  height: 100vh;
}

aside {
  /* 14% of viewport's width */
  width: 14vw;
  /* and so on ... */
  margin-right: 0.5vw;
}

main {
  width: 85.5vw;
}
&#13;
<!DOCTYPE html>
<html>

<body>
  <aside>aside</aside>
  <main>main</main>
</body>

</html>
&#13;
&#13;
&#13;

答案 5 :(得分:1)

这是一个简单的css解决方案

body {
     white-space: nowrap;
}

aside, main { 
     white-space: normal;
}

但是由于您试图完全避免使用样式元素,或者可以使用JavaScript等效样式设置器:

<!DOCTYPE html>
<html>    
    <body> 

        <aside></aside>

        <main></main> 

        <script>
          var h = screen.height/100;
          var w = screen.width/100;

          var e = document.getElementsByTagName("aside")[0].style;
          e.whiteSpace = "normal";
          e.display = "inline-block";
          e.backgroundColor = "lightblue";
          e.width = 14*w + "px";
          e.height = 69*h + "px";
          e.marginRight = 0.5*w + "px";

          e = document.getElementsByTagName("main")[0].style;
          e.whiteSpace = "normal";
          e.display = "inline-block";
          e.backgroundColor = "green";
          e.width = 85.5*w + "px";
          e.height = 69*h + "px";   

          e = document.getElementsByTagName("body")[0].style;
          e.margin = e.padding = "0";
          e.whiteSpace = "nowrap";
         /*additional precaution*/
          e.overflow = "visible";
          e.backgroundColor = "black";
        </script>
    </body>
</html>

但是,我注意到你的计算取决于屏幕尺寸值,这很可能是最初问题的起源。

问候。

答案 6 :(得分:1)

我找到了原因!

将您的HTML更改为

<aside></aside><main></main> 

标签之间没有空格,因为显然内联块元素确实会在它们之间占用一个鬼空间!通过删除它们之间的空格或在两者之间添加空白注释来解决这个问题。

  

这不是一个&#34;错误&#34; (我不这么认为)。它只是在一条线上设置元素的方式。您希望键入的单词之间的空格是空格吗?这些块之间的空间就像单词之间的空格。这并不是说规范无法更新以说内联块元素之间的空格应该没什么,但我相当肯定这是一个巨大的蠕虫,不可能永远发生。

了解更多here.

以下是演示JS FIDDLE