当父元素指定了尺寸时,才继承尺寸。

26

我正在使用 Web Components 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>的宽度或高度上应用百分比时,这种方法不起作用。相反,子元素会占据其父元素相同的百分比空间

我已经尝试了各种其他解决方案并进行了广泛搜索,但都没有找到解决办法。我认为纯CSS的解决方案可能是不可能的,但我希望有人能证明否定的结论是错误的。

澄清一下:最终结果应该是<my-el>本身表现得像一个内联替换元素,就好像它是具有自己内部尺寸的<img>元素一样。当您在这些元素上不设置宽度或高度时,它们默认使用其内部尺寸。当您设置宽度或高度时,它们将优先采用,并且任何“内部”内容都会相应调整大小。(至少,我希望能够说明问题!)


1
它应该是子元素的默认大小。我显然误解了,但为什么width/height:100%不适用于子元素? - AmmarCSE
没关系,我现在看到了 http://jsfiddle.net/6vygke92/1/ - AmmarCSE
假设容器宽度为400像素,当父元素的宽度为50%(解析为200像素)且子元素继承此值时,您实际上想要什么?您希望子元素以像素为单位与父元素具有相同的宽度吗? - sp00m
@sp00m,正确。我可能需要用更多的例子来澄清这个问题,因为它在现有形式下似乎很难理解。 - Andy E
1
这个问题可以通过来自 CSS Display 3my-el { display: contents; } 解决。奇迹般的是,至少在 Firefox 37+ 中存在一种实现,使我能够构建 此演示 - BoltClock
显示剩余3条评论
6个回答

7
您可以使用min-width:100%min-height:100%作为备用方案,以应对将百分比宽度分配给父div的情况:
 my-el img, my-el canvas {
   width: inherit;
   height: inherit;
   max-width: inherit;
   min-width:100%;
   max-height: inherit;
   min-height: 100%;
 }

fiddle


嗯,我们可能有一个赢家。我还必须为y维度应用min-height: 100%作为相同的回退,但是经过简短的试验,我似乎找不到它无法覆盖的任何边缘情况。当我有空闲时间时,我会再玩一下,如果它涵盖了所有基础知识,您将获得勾选标记。 - Andy E
我已经尝试过一些操作,但是我找不到任何它无法运行的情况... - maioman
1
我已经转而采用@Pangloss的答案,因为它在技术上更好。不过,我又添加了一个赏金,明天会授予给你以弥补这个情况。 - Andy E

6
百分比宽度和高度是相对于父元素的,因此我认为您可能只需要使用这个。
my-el {
    display: inline-block;
}
my-el img, my-el canvas {
    width: 100%;
    height: 100%;
}

随意设置my-el的任何宽度和高度,看看是否适合您。

http://jsfiddle.net/6afdbfck/


1
尴尬地说,我认为这可能会完成任务。这是我尝试的第一件事,在经历了很多挫折和提问之后,我发现自定义元素上设置了 display: block,这是冲突的原因。 - Andy E

2

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

my-el {display: inline-block;}

为确保子元素采用父元素的属性,请使用以下代码:
my-el > img,
my-el > canvas {
    height: auto;
    max-width: 100%;
    width: 100%;
}

值得一提的是,最好给您的元素添加一个类作为钩子,并将样式附加到该类而不是直接针对该元素进行操作,例如:

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

1
问题在于API用户可能想要在“my-el”(这是一个自定义元素而不是类)上指定自己的尺寸,这些尺寸不会被“img”、“canvas”或者其他我想要的元素继承。我试图隐藏实现细节,让用户把它当作内联替换元素本身来处理,就像“img”或“canvas”一样。 - Andy E
2
好的,所以您希望子元素继承其父元素的大小。您的问题读反了。我会更新我的答案。 - Seth Warburton
使用类会使自定义元素失去意义(而且也没有什么实际区别)。此外,你的建议并不真正有效height: auto 意味着 img 永远不会采用父元素设置的 height - Andy E
height: auto; 确保您的图像不会因适应父级高度而被扭曲,这是在生产中需要避免的情况。使用样式类可以提供更高的特异性,从而有助于避免意外和不必要的冲突,并增加稳健性,使您可以更改元素名称而无需重写样式。 - Seth Warburton
我认为你没有理解我为什么要将自定义元素作为库的一部分提供。使用类会减少使用自定义元素的透明度;如果第三方想要操作该元素,他们需要确保类保持完整。此外,特定性需要更低,以便样式可以轻松地被覆盖。将我应用的样式视为浏览器提供的元素的默认样式。这些样式具有最低的特定性,以便任何开发人员定义的CSS规则都将覆盖它们。 - Andy E

0

我觉得我不理解这个问题。如果您能够在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;
}

0
你的客户如何在自定义元素上设置宽度或高度? 无论如何,你可以这样做:
my-el img, my-el canvas {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
}

它指定img/canvas的宽度与默认值相同,但不要超出其父元素的宽度。 图片将保留其纵横比,在它们下方或右侧留出空白,您可以在此fiddle(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元素,则您的解决方案无法正常工作。http://jsfiddle.net/yrvfz1fw/3/ - Andy E
我们可以为图像添加 height: 100% 并设置 display: block(画布默认为块)。您是否需要强制执行给定的(或图像)纵横比?http://jsfiddle.net/vendruscolo/yrvfz1fw/5/ - Alessandro Vendruscolo
画布元素默认情况下不是块级元素,它们是内联替换元素。如果自定义元素本身没有设置尺寸,则您的解决方案会出现问题,因为图像的纵横比未被保持。 - Andy E
在这里https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements,他们说它是块级元素,但这不是重点。我已经更新了我的答案,考虑到图像的纵横比。 - Alessandro Vendruscolo
你说得对,它们是块级元素(尽管它们仍然是替换元素,这就是让我感到困惑的地方)。 - Andy E

0

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

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及其子元素并期望它处于流中,这种方法就会失败。通常情况下,在不改变页面上的任何其他内容的情况下绝对定位一个元素并不是一个好主意,因为它可能会对布局产生负面影响。 - BoltClock
此外,请不要随意标记您的答案以引起版主的注意,除非您确切了解版主的职责。标记链接不是玩具。 - BoltClock
谢谢你的建议“标志链接不是玩具”,能否请您提供其他内容的问题,因为我无法弄清楚?谢谢。 - Mohammed Moustafa
你能看到我提供的另外两种方式的代码吗? - Mohammed Moustafa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接