仅当在父元素上指定维度时才继承维度

Posted

技术标签:

【中文标题】仅当在父元素上指定维度时才继承维度【英文标题】:Inheriting dimensions only if they are specified on the parent element 【发布时间】:2015-08-28 11:38:51 【问题描述】:

我正在使用 Web 组件 polyfill 为 API 开发一堆自定义元素,但遇到了困难。

其中一个元素可能包含<img><canvas> 元素。如果没有为自定义元素指定尺寸,它应该是子元素的默认尺寸。如果指定了一个或多个维度,它们应该被子元素继承。

对于我的第一次尝试,我认为 CSS inherit 的值就足够了:

my-el img, my-el canvas 
    width: inherit;
    height: inherit;
    max-width: inherit;
    min-width: inherit;
    max-height: inherit;
    min-height: inherit;

但是,当对<my-el> 的宽度或高度应用百分比时,这不起作用。取而代之的是子元素takes up the same percentage of its parent。

我已经尝试过各种其他解决方案,但无济于事。我认为纯 CSS 解决方案可能是不可能的,但我希望有人能证明并非如此。

澄清一下,最终结果应该是<my-el> 本身的行为就像一个内联替换元素,就好像它是一个具有自己内部尺寸的<img>。当您没有在这些元素上设置宽度或高度时,它们默认为其内部尺寸。当您确实设置宽度或高度时,这具有优先权,并且任何“内部”内容都会相应地调整大小。 (至少,我希望澄清一下!)

【问题讨论】:

it should be the default size of the child element. 我显然误解了,但为什么 width/height:100% 不能为子元素工作? 没关系,我现在看到了jsfiddle.net/6vygke92/1 假设容器是 400px 宽,当父级有 50% 的宽度(解析为 200px)并且子级继承了这个值,你到底想要什么?子级与父级具有相同的宽度以像素为单位 @sp00m,正确。我可能不得不用更多的例子来澄清这个问题,因为目前的形式似乎很难理解。 这个问题可以通过CSS Display 3 中的my-el display: contents; 来解决。神奇的是,Firefox 37+ 中至少存在一种实现,允许我构造 this demo。 【参考方案1】:

我希望这次我的代码能正常工作

my-el 
    width: 50%;
    border: 1px solid silver;


my-el img, my-el canvas 
    width: inherit;
    height: inherit;
    max-width: inherit;
    min-width: inherit;
    max-height: inherit;
    min-height: inherit;
    position: relative;
<my-el>
  <img src="https://s3-eu-west-1.amazonaws.com/uploads-eu.hipchat.com/214790/1500400/lX8QKASWLAKotii/29e222d6-5828-4c3e-8153-5d5d065e91b1-original.png" />
</my-el>

或者其他方式

my-el 
  width: 50%;
  border: 1px solid silver;

my-el img,
my-el canvas 
  width: inherit;
  height: inherit;
  max-width: inherit;
  min-width: inherit;
  max-height: inherit;
  min-height: inherit;
  position: absolute;
  right: 0;
  left: 0;
  top: 0;
  bottom: 0;
<my-el>
  <img src="https://s3-eu-west-1.amazonaws.com/uploads-eu.hipchat.com/214790/1500400/lX8QKASWLAKotii/29e222d6-5828-4c3e-8153-5d5d065e91b1-original.png" />
</my-el>

我希望这次可以帮助您以一种简单的方式和更少的代码,并且兼容所有浏览器以及响应式,而且它完全,完美并且不显示my-el 的边框。 如果您有任何问题,请告诉我。

【讨论】:

一旦页面上有任何其他内容,例如如果有一个未定位的祖先具有自己的宽度,或者如果在 my-el 及其子项之后有 任何 其他内容期望它处于流动状态。一般来说,绝对定位一个元素而不改变页面上的任何其他内容并不是一个好主意,因为它可能并且将会对布局产生不利影响。 另外,除非您了解版主的具体工作,否则请停止标记您的答案以引起版主的注意。国旗链接不是玩具。 感谢您的建议“标志链接不是玩具”,您能否提供其他内容的问题,因为我无法弄清楚?谢谢 你能看到我提供的另外两种方法的代码吗?【参考方案2】:

百分比宽度和高度是相对于父元素的,所以我认为你可能只使用它。

my-el 
    display: inline-block;

my-el img, my-el canvas 
    width: 100%;
    height: 100%;

随意将任意宽度和高度设置为my-el,看看它是否适合你。

http://jsfiddle.net/6afdbfck/

【讨论】:

令人尴尬的是,我认为这可能会起作用。这是我尝试的第一件事,在经历了很多挫折并提出了这个问题后,我发现 display: block 被设置在自定义元素上,这是冲突的。【参考方案3】:

对于将百分比宽度分配给父 div 的情况,您可以使用 min-width:100% - min-height:100% 作为后备:

 my-el img, my-el canvas 
   width: inherit;
   height: inherit;
   max-width: inherit;
   min-width:100%;
   max-height: inherit;
   min-height: 100%;
 

fiddle

【讨论】:

嗯,我们可能在这里有一个赢家。我还必须将min-height: 100% 应用为 y 维度的相同后备,但只是短暂的玩耍,我似乎找不到任何它没有涵盖的边缘情况。当我有空闲时间时,我会再玩一些,如果它涵盖了所有基地,你就会得到滴答声。 我用它玩了一点,我找不到它不起作用的场景...... 我已切换到@Pangloss 的答案,因为它在技术上更好。但是,我已经添加了另一个赏金,明天我会奖励给你以弥补它。【参考方案4】:

您的客户如何设置自定义元素的宽度或高度? 无论如何,你可以这样做:

my-el img, my-el canvas 
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;

它说img/canvas 与它们的默认值一样宽,但不能比它们的父级宽。 图像将保持它们的纵横比,在它们下方或右侧留下空白空间,正如您在这个小提琴中看到的 http://jsfiddle.net/vendruscolo/yrvfz1fw/9/

如果您希望图像被拉伸以填充可用空间,您可以改为这样做

my-el img, my-el canvas 
    display: block;
    width: 100%;
    height: 100%;

只要您使用百分比或较小的宽度调整元素大小,就可以了。当您使用像素设置显式(更大)宽度时,图像将停止以保持其纵横比,如您所见http://jsfiddle.net/vendruscolo/zz6gnytt/2/ 在这种情况下,如果您想保持纵横比,则必须查询图像的naturalWidthnaturalHeight 并自行计算以保持纵横比。

【讨论】:

客户端会使用自己的 CSS 样式表来应用样式。我希望元素对他们来说尽可能透明。如果自定义元素上的 heightwidth 大于 img/canvas 元素,您的解决方案将不起作用。 jsfiddle.net/yrvfz1fw/3 我们可以为图片添加height: 100%并设置display: block(画布默认是块)。您是否必须强制执行给定(或图像)的纵横比? jsfiddle.net/vendruscolo/yrvfz1fw/5 canvas 元素 不是 默认情况下的块元素,它们是内联 replaced 元素,并且由于未保留 img 的纵横比,您的解决方案被破坏当自定义元素本身没有设置尺寸时。 这里developer.mozilla.org/en-US/docs/Web/html/Block-level_elements 他们说这是一个块元素,但这不是重点。我已经更新了我的答案,以考虑图像的纵横比。 你是对的,它们是块元素(尽管它们仍然被替换,这让我很困惑)。【参考方案5】:

除非我完全误解了您的要求,否则您只需要:

my-el display: inline-block;

确保子元素采用父元素的属性:

my-el > img,
my-el > canvas 
    height: auto;
    max-width: 100%;
    width: 100%;

FWIW,最好将一个类添加到您的元素中,作为一个钩子,并将您的样式附加到该元素上,而不是直接定位元素,例如:

<myelement class="my-el"><img></myelement>

.my-el display: inline-block;

.my-el > img,
.my-el > canvas 
    height: auto;
    max-width: 100%;
    width: 100%;
 

如果您希望将这些样式应用于作为父元素的直接子元素的 任何 元素,则只需使用通用选择器:

.my-el > * 
    height: auto;
    max-width: 100%;
    width: 100%;
 

【讨论】:

问题是API用户可能想在my-el(这是一个自定义元素,不是一个类)上指定他们自己的维度,这不会被img继承,@ 987654328@ 或任何我想要的。我试图向用户隐藏实现细节,因此他们可能会将其视为内联替换元素本身,就像 imgcanvas 一样。 对,所以您希望子代继承其父代的大小。你的问题反过来读了。我会更新我的答案。 使用类违背了它是自定义元素的意义(也没有真正的区别)。另外,您的建议doesn't really work、height: auto 意味着img 永远不会采用父级设置的height height: auto; 确保您的图像永远不会被扭曲以适应父级的高度,我敢肯定您在生产中需要避免这种情况。使用样式类可以提供更高的特异性,这可能有助于避免不必要的和意外的冲突,并增加了健壮性,使您可以更改元素名称而无需重写样式。 我认为您错过了为什么我将自定义元素作为库的一部分提供的原因。使用类会降低使用自定义元素的透明度;如果第三方想要操纵元素,他们需要确保类保持完整。此外,特异性需要较低,以便可以轻松地覆盖样式。将我应用的样式想象成类似于浏览器提供的元素的默认样式。这些具有最低的特异性,因此任何开发人员定义的 CSS 规则都会覆盖它们。【参考方案6】:

我想我不明白这个问题。如果您能够在 img/canvas 上设置内联样式,那么您应该使用 width/height: 100% 进行排序,因为这些将被内联样式覆盖。

我包含了一个 JSFiddle,在其中我在其中一个元素上设置了内联样式,另外两个采用了父元素。

http://jsfiddle.net/6vygke92/5/

.my-el img, .my-el canvas     
    display: block; 
    width: 100%;
    height: 100%;
    max-width: inherit;
    min-width: inherit;
    max-height: inherit;
    min-height: inherit;

【讨论】:

以上是关于仅当在父元素上指定维度时才继承维度的主要内容,如果未能解决你的问题,请参考以下文章

js在父元素上添加点击事件,怎么阻止子元素继承父元素的点击事件?

js在父元素上添加点击事件,怎么阻止子元素继承父元素的点击事件

连续数组多维表示的快速元素访问

线性空间维度的公式是啥?

[ jquery 选择器 :nth-last-of-type() ] 选取指定(p)父元素下的从后向前数的指定第一个子元素(无关目标元素在父元素中所处的位置)

css里怎么去掉从父级元素继承下来的 css 样式吗