防止 div 扩大父表的宽度

cdh*_*wie 5 html css

我正在开发一个项目,我将把标记注入到我无法控制的页面(嵌入脚本)中。出现了一个有趣的情况,我注入的 div 包含在表中。overflow-x: auto我的 div 的子级是一个水平菜单,当它超过父元素的宽度时,应该滚动 ( ) ,但在父元素是没有 的 table-layout: fixed表格的情况下,我注入的内容反而会导致父表格展开,严重破坏一些布局。

在本例中,表格包含在固定宽度的 div 中,如下所示:

<div style="width: 600px;">
  <table width="100%">
    <tr>
      <td>
        <div> <!-- my content --> </div>
      </td>
    </tr>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

我发现table-layout: fixed桌子上的设置可以解决这个问题。然而,这个标记超出了我的控制范围——我只能从最里面的 div 开始更改标记/CSS。

我确实找到了一种有效的方法:width: 100%; display: table; table-layout: fixed;在我的 div 上进行设置。但是,我不确定这是否符合任何相关规范,因为该display: tablediv 的内容都是display: block.

这是重现问题并演示黑客攻击的标记:

<div class="outer">
  <table class="bad-table">
    <tr>
      <td>
        <div class="wrapper">
          <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
          <div class="target">
            <ul class="menu">
              <li style="background-color: #800;"></li>
              <li style="background-color: #880;"></li>
              <li style="background-color: #080;"></li>
              <li style="background-color: #008;"></li>
            </ul>
          </div>
          <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
        </div>
      </td>
    </tr>
  </table>
</div>

<div class="outer">
  <table class="bad-table">
    <tr>
      <td>
        <div class="wrapper hack">
          <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
          <div class="target">
            <ul class="menu">
              <li style="background-color: #800;"></li>
              <li style="background-color: #880;"></li>
              <li style="background-color: #080;"></li>
              <li style="background-color: #008;"></li>
            </ul>
          </div>
          <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
        </div>
      </td>
    </tr>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

CSS:

.outer {
  width: 200px;
  border: 1px solid #0f0;
}

.bad-table {
  width: 100%;
  border: 1px solid #f00;
}

.target {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
}

.wrapper {
  width: 100%;
}

.wrapper.hack {
  display: table;
  table-layout: fixed;
}

ul.menu {
  list-style: none;
  padding: 0;
  margin: 0;
  white-space: nowrap;
  width: 100%;
}

ul.menu li {
  display: inline-block;
  width: 100px;
  height: 50px;
  padding: 0;
  margin: 0;
}
Run Code Online (Sandbox Code Playgroud)

小提琴

请注意,在第一个示例中,菜单块导致表格(红色边框)扩展到其包含的 div(绿色边框)之外。与第二个示例相比,第二个示例使用我的(违反标准?)黑客成功阻止父表增长,同时还允许滚动菜单块。(使用 Chrome 和 Firefox 进行测试。)

请注意以下限制:

  • 我绝对无法在注入的 div 之外编辑标记。这包括在我注入的 div 之外操作 DOM,因为我不知道我对其他人文档的更改可能会导致什么不良影响。
  • 我注入的 div 的高度应该基于其内容(按照正常的文档流),这意味着使用的解决方案position: absolute往往会出现问题,因为它们将从页面流中删除我的内容,使前面和/或后面的内容与注入的内容重叠分区 通常的修复方法(设置固定高度)意味着我的元素将无法调整其高度以匹配其内容。

这个黑客是解决这个问题的合法方法,还是有更好的方法?

LGS*_*Son 3

table总是很棘手,但我position: absolute在很多情况下都成功使用过,所以我的答案/问题是:这对你有用吗?

但请注意,wrapper仅仅是一个包装器,应该只包含target,因此所有内容都会进入target,否则target将会与其同级内容重叠,除非设置了固定的边距/填充。

.outer {
  width: 200px;
}

.bad-table {
  width: 100%;
}

.wrapper {
  position: relative;
}
.target {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: auto;
  overflow: auto;
}

ul.menu {
  list-style: none;
  table-layout: fixed;
  padding: 0;
  margin: 0;
  white-space: nowrap;
  width: 100%;
}
ul.menu li {
  display: inline-block;
  width: 100px;
  height: 50px;
  padding: 0;
  margin: 0;
}
Run Code Online (Sandbox Code Playgroud)
<div class="outer">
  <table class="bad-table">
    <tr>
      <td>
        <div class="wrapper">
          <div class="target">
          
          
            <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
            <ul class="menu">
              <li style="background-color: #800;"></li>
              <li style="background-color: #880;"></li>
              <li style="background-color: #080;"></li>
              <li style="background-color: #008;"></li>
            </ul>
            <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>


          </div>
        </div>
      </td>
    </tr>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

为了进行比较,这里是使用相同的代码片段display: table

.outer {
  width: 200px;
}

.bad-table {
  width: 100%;
}

.wrapper {
  width: 100%;
  display: table;
  table-layout: fixed;
}
.target {
  overflow: auto;
}

ul.menu {
  list-style: none;
  table-layout: fixed;
  padding: 0;
  margin: 0;
  white-space: nowrap;
  width: 100%;
}
ul.menu li {
  display: inline-block;
  width: 100px;
  height: 50px;
  padding: 0;
  margin: 0;
}
Run Code Online (Sandbox Code Playgroud)
<div class="outer">
  <table class="bad-table">
    <tr>
      <td>
        <div class="wrapper">
          <div class="target">
          
          
            <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>
            <ul class="menu">
              <li style="background-color: #800;"></li>
              <li style="background-color: #880;"></li>
              <li style="background-color: #080;"></li>
              <li style="background-color: #008;"></li>
            </ul>
            <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet pharetra nunc at condimentum.</div>


          </div>
        </div>
      </td>
    </tr>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)


更新

经过更多测试并阅读这些内容后,

我找不到任何其他方法来解决这种情况,因此,如果在不受控制的外部 div/table之前和之后存在内容,而您的内容 div的内容需要具有正常的流程,position: absolute则可能无法工作,具体取决于其余部分的方式页面内容的一部分已设置,但display: table; table-layout: fixed将会。

根据上述来源,使用display: table1不应该出现任何合规性问题,尽管您需要测试主要浏览器中的行为,因为它们都可能处理div's insidetd的不同(我确实测试了 Chrome,FF, Edge、Windows 上的 IE11,全部有效)。


1具体来说,此文本允许display: block元素直接位于元素内部display: table,因为中间表格行和表格单元格框会自动创建为匿名:

  1. 生成缺失的子包装器:
    1. 如果“table”或“inline-table”框的子 C 不是正确的表子项,则在 C 周围以及 C 的所有不是正确的表子项的连续兄弟项生成一个匿名“table-row”框。
    2. 如果行组框的子 C 不是“表行”框,则在 C 周围以及 C 的所有不是“表行”框的连续同级框生成匿名“表行”框。
    3. 如果“table-row”框的子 C 不是“table-cell”,则在 C 周围以及 C 的所有不是“table-cell”框的连续同级框生成一个匿名“table-cell”框。