Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using object-fit on a <div> with child elements, including a <canvas>

Tags:

I have an outer container that is variable in size and width. Suppose that inside this container, I have a canvas that I want to have grow as much as it can while maintaining proportion and not cropping. For this, I would normally use object-fit: contain.

Now, suppose instead of just a canvas, I have a canvas with another element placed next to it.

HTML:

<div class="outerContainer">   <canvas width="640" height="360"></canvas>   <div class="beside">   </div> </div> 

CSS:

.outerContainer {   display: flex;   border: 0.5em solid #444;   margin-bottom: 2em;   object-fit: contain; }  .outerContainer canvas {   flex-grow: 1;   background: #77a; }  /* This element has a fixed width, and should be whatever height the <canvas> is */ .outerContainer .beside {   flex-basis: 3em;   flex-grow: 0;   flex-shrink: 0;   background: #7a7; } 

In this case, I want to scale the whole outerContainer size, just like I did with canvas. The problem is that object-fit doesn't actually scale the element... it scales its contents. This doesn't seem to apply to normal block elements, resulting in a case where the canvas inside is potentially skewed if there is enough width.

Badly skewed canvas

If I add object-fit: contain to the canvas element, it maintains proportion but still uses the full width, meaning the .beside element is all the way to the right. This is visualized with the purple background on the canvas.

Not skewed but not correct

What I would like is the outerContainer to be scaled with the canvas contents, so that .beside always has the height of the canvas contents. The .outerContainer should be centered in the parent element, taking up as much space as it can without distorting the canvas. Like this, at any proportional scale:

Desired image

Is this doable with modern CSS? Or must I use a scripted solution?

Fiddle with examples: https://jsfiddle.net/nufx10zc/

like image 920
Brad Avatar asked Oct 04 '16 18:10

Brad


People also ask

How do I fit an image into a div in CSS?

To auto-resize an image or a video to fit in a div container use object-fit property. It is used to specify how an image or video fits in the container. object-fit property: This property is used to specify how an image or video resize and fit the container.

Why is object-fit not working in CSS?

For object-fit to work, the image itself needs a width and height . In the OP's CSS, the images do not have width and/or height set, thus object-fit cannot work.

How do you use object-fit property?

The object-fit property is used to specify how an <img> or <video> should be resized to fit its container. This property tells the content to fill the container in a variety of ways; such as "preserve that aspect ratio" or "stretch up and take up as much space as possible".

What does object-fit cover and object-fit contain mean?

contain - The image keeps its aspect ratio, but is resized to fit within the given dimension. cover - The image keeps its aspect ratio and fills the given dimension. The image will be clipped to fit. none - The image is not resized. scale-down - the image is scaled down to the smallest version of none or contain.


1 Answers

I don't know if it's ok for you, but I think it can be done mostly in css if you allow a little bit more HTML.

Consider the following html

<div class="outerContainer">   <div class="canvasContainer">       <canvas width="640" height="360"></canvas>   </div>   <div class="beside">   </div> </div> 

I just added a little div around the canvas. This way we let the canvas handle it's things and we use the div for the flex things.

Using the following css:

* {   box-sizing: border-box; }  .outerContainer {   display: flex;   border: 0.5em solid #444;   margin-bottom: 2em; }  .canvasContainer canvas {   width: 100%;   background: #777;   margin-bottom: -4px }  .canvasContainer {   flex-grow: 1;   background: #77a; }  /* This element has a fixed width, and should be whatever height the <canvas> is */ .outerContainer .beside {   flex-basis: 3em;   flex-grow: 0;   flex-shrink: 0;   background: #7a7; } 

We have canvas container taking all the available space. And then the canvas adapt accordingly with the image scaling in it. However I don't know why, there was a bit of a margin on the bottom of the canvas, hence the negative margin on it.

fiddle: https://jsfiddle.net/L8p6xghb/3/

As a side note, if you're looking to use that for captions, there are html5 element for it, like <figure> and <figcaption>!

like image 97
Py. Avatar answered Sep 28 '22 12:09

Py.