Inheriting dimensions only if they are specified on the parent element

4.8k views Asked by At

I'm developing a bunch of custom elements for an API using a web components polyfill and I've hit a snag.

One of the elements may contain an <img> or <canvas> element. If no dimensions are specified for the custom element, it should be the default size of the child element. If one or more dimensions are specified, they should be inherited by the child element.

For my first effort, I thought the CSS inherit value would be good enough:

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

However, this doesn't work when a percentage is applied to the width or height for <my-el>. Instead, the child element takes up the same percentage of its parent.

I've tried various other attempts at a solution and searched far and wide to no avail. I think a pure CSS solution may be impossible but I'm hoping someone can prove otherwise.

To clarify, the end result should be that <my-el> behaves like an inline-replaced element itself, as if it were an <img> with its own internal dimensions. When you don't set width or height on those elements, they default to their internal dimensions. When you do set width or height, that takes precedence and any "internal" content is resized accordingly. (At least, I hope that clarifies!)

6

There are 6 answers

1
Stickers On BEST ANSWER

The percentage width and height are relative to the parent element, so you could probably just use this I think.

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

Feel free to play around by setting any width and height to my-el, see if it works for you.

http://jsfiddle.net/6afdbfck/

0
Kevin Farrugia On

I think I don't understand the question. If you are able to set inline styles on the img/canvas then you should be sorted using width/height: 100% as these will be overriden by the inline-styles.

I included a JSFiddle where I set inline-styles on one of the elements and the other two which take the parents'.

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;
}
3
maioman On

You could use min-width:100% - min-height:100% as a fallback for the situation in which a percentage width is assigned to parent div:

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

fiddle

5
Alessandro Vendruscolo On

How do your clients set the width or height on the custom element? Anyway, you can do this:

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

It says the img/canvas to be as wide as their default is, but to not be wider than their parent. Images will keep their aspect ratios, leaving empty space below them or on the right side, as you can see in this fiddle http://jsfiddle.net/vendruscolo/yrvfz1fw/9/

If you want images to be stretched to fill the available space you can instead to this

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

As long as you size elements with percentages or with smaller widths, you're fine. When you set an explicit (larger) width using pixels the image will stop to maintain its aspect ratio, as you can see http://jsfiddle.net/vendruscolo/zz6gnytt/2/ In that case, if you want to maintain the aspect ratio you'll have to query the naturalWidth and naturalHeight of the image and do your own math to keep the aspect ratio.

5
Seth Warburton On

Unless I totally misunderstand your requirements then all you need is:

my-el {display: inline-block;}

To ensure the child element adopts the attributes of the parent use:

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

FWIW, it's probably better to add a class to your element, as a hook, and attach your styles to that rather than target the element directly, e.g:

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

.my-el {display: inline-block;}

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

If you want these styles to apply to any element that is a direct child of your parent element then just use the universal selector:

.my-el > * {
    height: auto;
    max-width: 100%;
    width: 100%;
 }
4
Mohammed Moustafa On

I hope this time my code will works

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>

Or another way to do it

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>

I hope this time will help you with an easy way and less code and compatible with all browsers as well as responsive too, Also it's exactly, perfect and doesn't show the border of my-el {}. Let me know if you have any question.