【问题标题】:Elements do not find enough space inside body - JavaScript styling元素在正文中找不到足够的空间 - JavaScript 样式
【发布时间】:2016-03-02 01:52:57
【问题描述】:

相关信息:

页面包含两个元素:

  • <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 并缩小(以便元素占用更少的空间)并重新放大,这将得到修复(我不知道为什么,也不要问我我是怎么发现的)。

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

假设(可略过):

浏览器似乎在想“如果我显示滚动条,即使它们不需要它们会发生什么?”,然后注意到滚动条的宽度 > 0,这意味着 @987654331 @ 和 <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>

【问题讨论】:

  • 你设置html, body {margin: 0; }并使用box-sizing: border-box了吗?
  • 另一个提示,因为您已经使用百分比来计算大小,请将设置大小设置为 px,使用 % 并且您可以跳过计算,因为浏览器会为您执行此操作,这将提高性能。
  • 另一个技巧,使用vh(视口高度)和vw(视口宽度),相当于屏幕的高度和宽度。
  • @JanNahody 不,绝对不一样。它可能会给你同样的结果,如果浏览器在最大化或剧院模式下运行。
  • @LGSon 你是对的。屏幕意味着设备大小。我忘了。

标签: javascript html css responsive-design


【解决方案1】:

问题编辑后更新

你的main 被推到aside 下的原因是因为你有一个不可见的空间,在你的情况下是换行符,但也可以是一个简单的空格,在你的标记中的元素之间,实际上添加尺寸以及使其全部超过 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>

注意:

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


使用您现有的代码,并且由于您不使用正常流程,因此可以选择绝对定位。

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

【讨论】:

  • DOM没有完全完成的原因是什么?你知道吗?
  • @Gendarme 不知道,它应该可以工作,但显然不行。正如我在之前我们删除的一个 cmets 中所写的,将 2 个内联块彼此相邻排列的正常方法是使用 white-space: nowrap,当使用它时,您不需要延迟、字体大小技巧,边距等...它可以正常工作,就像我制作的这个演示小提琴一样:jsfiddle.net/cvfht4om
  • 我已经有了一个解决方案,给出了身体的宽度screen.width。我只是想知道发生了什么。
  • @Gendarme 发生的事情是您尝试将 2 个子元素(aside,main)并排挤入父元素(主体),其中子元素大于父元素,因此第二个由于没有地方,孩子被推倒。要么将孩子的宽度设置为父母(身体的宽度),要么告诉孩子不要换行。当人们了解它的工作原理时,所有这些都是基本的 html。现在,当这些子元素是内联元素时,它们有一个空白边距,在设置父元素宽度时也需要考虑这一点,因此像font-size: 0 等技巧。
  • 我明白你在描述什么。我不明白的是,当你添加元素时,body 的大小是如何变化的,以及为什么延迟会修复它。有时间我可能会问这个问题。
【解决方案2】:

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

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

【讨论】:

  • 有时正确的答案很简短。 ;)
【解决方案3】:

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

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

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

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

但是你想保留你的html缩进,你也可以使用html cmets&lt;!-- --&gt;:

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

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

【讨论】:

    【解决方案4】:

    几乎完整的解释:

    以下工作(但也有其他方法):

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

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

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

      • 当浏览器最大化时,主体的最大宽度是浏览器窗口的宽度,而不是屏幕的宽度。元素的组合宽度现在大于主体的宽度,因此出现了这种行为。为 body 提供 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>
    

    【讨论】:

    • 解释很简单:行内块元素被视为字符,因此换行符和空格在它们之间创建实际的空格(空格字符)。 Font size: 0 删除这些空格,因为它使它们的大小为 0。
    【解决方案5】:

    我找到了原因!

    将您的 html 更改为

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

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

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

    阅读更多here.

    这是一个演示JS FIDDLE

    【讨论】:

    • 幻影空格是由于行内块元素被视为字符,因此换行符和空格在它们之间创建实际空格(空格字符)。我很确定这正是它应该是这样并且被指定的(因此 inline-block 中的'inline')。
    【解决方案6】:

    这是一个简单的 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>
    

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

    问候。

    【讨论】:

      【解决方案7】:

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

      元素有 display = "inline-block";

      你应该知道这是一个特殊的单位,你正在处理的事情:

      • vh : 视口高度
      • vw : 视口宽度

      示例

      注意:您可以忽略“视觉资料”部分

      /* 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;
      }
      <!DOCTYPE html>
      <html>
      
      <body>
        <aside>aside</aside>
        <main>main</main>
      </body>
      
      </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-09
        • 2018-03-25
        • 1970-01-01
        • 1970-01-01
        • 2022-11-11
        • 2017-05-14
        • 2013-07-21
        • 1970-01-01
        相关资源
        最近更新 更多