html – 防止div扩展父表的宽度

我正在开发一个项目,我将把标记注入我无法控制的页面(嵌入脚本).一个有趣的案例出现了,我的注入div包含在一个表中.我的div的子节点是一个水平菜单,当它超出父元素的宽度时应该滚动(overflow-x:auto),但是如果父元素是没有table-layout的表:fixed,我注入的内容而是导致父表扩展,可怕地打破一些布局.

在这种情况下,表包含在固定宽度的div中,如下所示:

<div style="width: 600px;">
  <table width="100%">
    <tr>
      <td>
        <div> <!-- my content --> </div>
      </td>
    </tr>
  </table>
</div>

我发现在表上设置table-layout:fixed修复了这个问题.但是,这个标记是我无法控制的 – 我只能从最里面的div开始更改标记/ CSS.

我找到了一个有效的黑客:设置宽度:100%;显示:表; table-layout:fixed;在我的div.但是,我不确定这是否符合任何相关的规范,因为这个显示内容:table div都是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>
      </td>
    </tr>
  </table>
</div>

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;
}

(Fiddle)

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

请注意以下约束:

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

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

解决方法

桌子总是很棘手,但是我使用了位置:在很多情况下绝对成功,所以我的答案/问题是:这对你有用吗?

请注意,包装器只是一个包装器,应该只包含目标,因此所有内容都会进入目标,否则目标将与其兄弟重叠,除非设置了固定的边距/填充.

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

为了比较,这里是使用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;
}
<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>


          </div>
        </div>
      </td>
    </tr>
  </table>
</div>

更新

经过一些更多的测试,并阅读这些,

> https://www.w3.org/TR/CSS2/tables.html#anonymous-boxes
> Is a DIV inside a TD a bad idea?

我找不到任何其他方法解决这种情况,所以如果你的内容div的内容需要具有正常流量的不受控制的外部div / table之前和之后的内容,position:absolute可能不起作用取决于页面的其余部分已设置,但显示:table; table-layout:固定会.

根据以上消息来源,使用display:table1应该没有任何合规性问题,虽然你需要测试主要浏览器中的行为,因为它们都可以处理div内部td的不同(我测试过Chrome,FF,Edge,Windows上的IE11,全部工作).

1具体来说,这个文本允许直接在display:table元素内部显示:block元素,因为中间的table-row和table-cell框会自动创建为匿名:

  1. Generate missing child wrappers:
    1. If a child C of a ‘table’ or ‘inline-table’ Box is not a proper table child,then generate an anonymous ‘table-row’ Box around C and all consecutive siblings of C that are not proper table children.
    2. If a child C of a row group Box is not a ‘table-row’ Box,then generate an anonymous ‘table-row’ Box around C and all consecutive siblings of C that are not ‘table-row’ Boxes.
    3. If a child C of a ‘table-row’ Box is not a ‘table-cell’,then generate an anonymous ‘table-cell’ Box around C and all consecutive siblings of C that are not ‘table-cell’ Boxes.

相关文章

vue阻止冒泡事件 阻止点击事件的执行 &lt;div @click=&a...
尝试过使用网友说的API接口获取 找到的都是失效了 暂时就使用...
后台我拿的数据是这样的格式: [ {id:1 , parentId: 0, name:...
JAVA下载文件防重复点击,防止多次下载请求,Cookie方式快速简...
Mip是什么意思以及作用有哪些