html center a canvas inside a div without stretching the canvas [duplicate] - css

This question already has an answer here:
What is the relation between the size and resolution of HTML5 canvas
(1 answer)
Closed 6 years ago.
I have a html like:
.image-detail {
height: 100%;
width: 100%;
display: block;
position: relative;
}
canvas {
display: block;
}
.image-detail-canvas {
-moz-user-select: none;
-webkit-user-select: none;
max-width: 100% !important;
max-height: 100% !important;
position: absolute !important;
left: 50% !important;
top: 50% !important;
transform: translate(-50%, -50%) !important;
}
<div class="image-detail">
<canvas class="image-detail-canvas" id="image-canvas">
</canvas>
</div>
It is centering the canvas but the canvas is stretching.
I dont want the canvas to be stretched.
I want it to be centered without stretching. If the canvas is horizontal center it horizontally and if vertical then so on.

Remove Position: absolute; and translate
Add some width to your canvas and put margin: 0 auto;, Hope that helps.
canvas {
border: 1px solid;
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.image-detail-canvas {
-moz-user-select: none;
-webkit-user-select: none;
max-width: 100% !important;
max-height: 100% !important;
}
<div class="image-detail">
<canvas class="image-detail-canvas" id="image-canvas" width="100" height="100">
</canvas>
</div>
Check here: https://stackoverflow.com/a/7782251/5336321

It should be sufficient to change position to absolute, plus add width/height definitions to all parent elements (also html and body):
html, body {
width: 100%;
height: 100%;
margin: 0;
}
.image-detail {
height: 100%;
width: 100%;
display: block;
position: relative;
}
canvas {
border: 1px solid;
display: block;
}
.image-detail-canvas {
position: relative;
max-width: 100%;
max-height: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
<div class="image-detail">
<canvas class="image-detail-canvas" id="image-canvas" width="100" height="100">
</canvas>
</div>

Related

CSS preserve ratio of circle on top of image

I have an image and i want to put 2 circles on top of it, instead of the eyes.
body {
background-color: lightgrey;
color: #fff;
padding: 0;
margin: 0;
}
main {
display: grid;
place-items: center;
position: relative;
}
#container {
min-height: 100vw;
min-width: 100vw;
background: none;
aspect-ratio: 1 / 1;
}
.eye-container {
position: relative;
border-radius: 50%;
background-color: red;
width: 12vw;
height: 12vw;
}
.eye-container.left {
top: -84%;
left: 36%;
}
.eye-container.right {
top: -96%;
left: 51%;
}
.eye {
position: absolute;
bottom: 3px;
right: 2px;
display: block;
width: 3vw;
height: 3vw;
border-radius: 50%;
background-color: #000;
}
img {
max-width: 100%;
min-width: 100%;
}
<main>
<div id="container">
<img id="sponge" src="https://upload.wikimedia.org/wikipedia/en/thumb/3/3b/SpongeBob_SquarePants_character.svg/220px-SpongeBob_SquarePants_character.svg.png">
<div class="eye-container left">
<div class="eye"></div>
</div>
<div class="eye-container right">
<div class="eye"></div>
</div>
</div>
</main>
The current issue is the image is too big, it is stretched.
The initial problem was that the layout was not responsive on mobile, and i've did some changes and now the image is this big.
I've used aspect-ratio: 1 / 1; because top was not working with negative percentage, and with pixels the eyes location is changing if is shrink the window.
Do you have another suggestion, maybe a simplified code will be better.
Thank you.
I'm a noob developer and I felt like, this was a tiny engineering job "LOL" but I did it for you.
So the most important point in this is to keep the image and the eyes in the same position. and to do that, you should position them in a parent container for image and eyes considering four important factors:
1- Parent position: relative; All children position: absolute;
2- All children's width: %; so it can stay in the same spot in its parent whatever the width of the parent is.
3- Eyes and eyeballs positioning top, left, right must be % too for the same purpose.
4- To change the image size, use the parent width. do not change the image size.
If you follow these steps, you can position any element with any image or other element.
* {
border: 1px solid blue;
margin: 0;
padding: 0;
}
.container {
width: 200px; /* use this to change the picture size. do not change it somewhere else */
position: relative;
}
.image {
width: 100%;
}
.eye-container{
position: absolute;
border-radius: 50%;
background-color: red;
width: 12%;
height: 12%;
}
.left-eye {
top: 17%;
left: 36%;
}
.right-eye {
top: 17%;
left: 51%;
}
.eyeball {
position: absolute;
bottom: 3px;
right: 2px;
display: block;
width: 30%;
height: 30%;
border-radius: 50%;
background-color: #000;
}
<div class="container">
<img class="image" src="https://upload.wikimedia.org/wikipedia/en/thumb/3/3b/SpongeBob_SquarePants_character.svg/220px-SpongeBob_SquarePants_character.svg.png">
<div class="left-eye eye-container">
<div class="eyeball"></div>
</div>
<div class="right-eye eye-container">
<div class="eyeball"></div>
</div>
</div>

Maintain the aspect ratio of an image that is within a circle

I am trying to make basic CSS challenges. In this case I have an image that I have given a circle, but I do not know what to do so that it retains its aspect ratio, does not fully cover the entire circle and is centered. This is the code I have. I want to learn a way to achieve this effect with any image of any resolution.
Desired effect:
img{
border-radius:50%;
width:300px;
height:300px;
border: solid 1px black;
}
.image_container{
display:flex;
justify-content:center;
align-items:center;
}
<div class="image_container">
<img src="https://danikalaw.com/wp-content/uploads/2017/08/r.png">
</div>
Set the sizing condition on the container rather than the image.
img{
width: 100%;
height: auto;
}
.image_container{
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
border: 1px solid black;
border-radius: 50%;
overflow: hidden;
padding: 30px;
}
<div class="image_container">
<img src="https://danikalaw.com/wp-content/uploads/2017/08/r.png">
</div>
You are using CSS on img that should be on .image-container. Then, you can set width for image enough to be centered and not override the circle, like this:
.image_container {
width:300px;
height:300px;
border-radius:50%;
border: solid 1px black;
display:flex;
justify-content:center;
align-items:center;
}
img {
width: 70%;
}
Maybe something like that?
* {
box-sizing: border-box;
}
img {
padding: 30px;
position: absolute; top: 50%; left: 0;
transform: translateY(-50%);
width: 100%;
}
.image_container {
border-radius: 50%;
border: solid 1px black;
overflow: hidden;
position: relative;
width: 300px; height: 300px;
}
<div class="image_container">
<img src="https://danikalaw.com/wp-content/uploads/2017/08/r.png">
</div>
Outline
Wrap <img> tag in a block level tag and then wrap that tag with another block level tag:
<section class="frame">
<figure class="logo">
<img class="image">
...
Assign the top ancestor tag (demo. section.frame)
position: relative;
width: 50vw;
height: 50vw;
Basic CSS positioning -- parent is relative -- child is absolute -- child references its relative parent's area for X, Y position. The value: 50vw is equivalent to 50% of viewport width. This makes the tag responsive and it will dynamically change it's dimensions and maintain aspect ratio whenever the viewport width changes.
Assign the parent tag of <img> tag (demo. figure.logo)
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
This positions it to the edges of section.frame.
Assign the <img> the following:
display: block;
width: 100%;
height: 100%;
object-fit: contain;
This will position img.image to the edges of figure.logo
Added a :hover effect to show how the img tag fits within the figure and section tags. Each tag is assigned border-radius: 50% so that there are no square corners overlapping the visible border on section.frame.
.frame {
position: relative;
width: 50vw;
height: 50vw;
border: 3px solid #B9BBC0;
border-radius: 50%;
}
.logo {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
border-radius: 50%;
}
.image {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 50%;
}
.frame:hover {
background-color: #000;
}
<section class='frame'>
<figure class='logo'>
<img class='image' src='https://danikalaw.com/wp-content/uploads/2017/08/r.png'>
</figure>
</section>
References
Viewport CCS Concepts
object-fit: contain property
position property

Chrome / Firefox inconsistent when parent is positioned with absolute

I have a map with rounded icons on it.
I'm using empty canvas elements to preserve 1:1 aspect ratio on rounded containers
When viewing in Chrome 67 everything is fine, but with Firefox 60 it does not work, aspect ratio is not preserved and icons have a content width of zero (only their padding make them visible)
It happens if parent (.zone) has position:absolute, however it work when .zone has position:relative.
I really need position:absolute, does somebody know why firefox does not expand width of .item to adjust to the canvas element ?
* {
margin: 0;
box-sizing: 0;
}
.zone {
position: absolute;
left: 5%;
right: 5%;
top: 5%;
bottom: 5%;
background: grey;
}
.item {
position: absolute;
transform: translate(-50%, -50%);
height: calc(100% / 11);
border-radius: 50%;
z-index: 3;
overflow: hidden;
cursor: help;
border: 1.5px solid #0acaff;
color: #0acaff;
}
.item canvas {
height: 100%;
}
.square_content {
background: red;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
align-items: center;
padding: 5px;
}
<div class="zone">
<!-- inline style is computed -->
<div class="item" style="left: 22.727%;top: 77.273%;">
<canvas width="1" height="1"></canvas>
<div class="square_content">
</div>
</div>
</div>
Note: on the snippet you should see mostly a gray zone with a perfectly rounded icon (blue border and red background)
The issue is with height: calc(100% / 11); it's value is not picking up in Firefox, if you change the % to vw your code will work fine.
A sample code for you:
* {
margin: 0;
box-sizing: 0;
}
.zone {
position: absolute;
left: 5%;
right: 5%;
top: 5%;
bottom: 5%;
background: grey;
}
.item {
position: absolute;
transform: translate(-50%, -50%);
height: 4vw;
/* or height: calc(40vw/11); */
border-radius: 50%;
z-index: 3;
overflow: hidden;
cursor: help;
border: 1.5px solid #0acaff;
color: #0acaff;
}
.item canvas {
height: 100%;
}
.square_content {
background: red;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
align-items: center;
padding: 5px;
}
<div class="zone">
<!-- inline style is computed -->
<div class="item" style="left: 22.727%;top: 77.273%;">
<canvas width="1" height="1"></canvas>
<div class="square_content">
</div>
</div>
</div>
The above sample work will all browsers, Hope this was helpful for you.

Firefox not ignoring fixed position elements when outside container width

I wasn't sure of the best way to explain this, but if you look at the example snippet in Chrome or Safari, the orange div does not cause the document to scroll horizontally when the window is narrower than the blue container. This is the desired behavior.
However, in Firefox, if you make the window narrow it counts the orange box as content that needs to be able to be scrolled to, causing the document to scroll to the right in an odd way that shifts the body content to the left and is ugly. What's also strange is that you'll notice the green box on the left DOESN'T cause it to have scrollable space to the left...is this a bug, or why is this happening?
Anyone else encountered this?
* {
box-sizing: border-box;
}
.wrapper {
max-width: 700px;
height: 200px;
margin: 0 auto;
}
.banner {
width: 100%;
height: 100%;
padding: 10px;
background-color: blue;
position: relative;
transform: scale(1);
color: #ffffff;
}
.banner:before, .banner:after {
content: '';
width: 100px;
height: 100%;
position: fixed;
left: -100px;
top: 0;
background-color: green;
}
.banner:after {
left: 100%;
background-color: orange;
}
.content {
width: 100%;
height: 300px;
padding: 10px;
background-color: #f1f1f1;
margin-top: 40px;
}
<div class="wrapper">
<div class="banner">Banner</div>
<div class="content">Content</div>
</div>
You can wrap that in an element that will scale with the viewport and set overflow: hidden on that element. You can also remove the transform: scale() from .banner and use position: absolute on the pseudo elements, unless scale(1) is needed for some reason.
* {
box-sizing: border-box;
}
header {
overflow: hidden;
}
.wrapper {
max-width: 700px;
height: 200px;
margin: 0 auto;
}
.banner {
height: 100%;
padding: 10px;
background-color: blue;
position: relative;
color: #ffffff;
}
.banner:before, .banner:after {
content: '';
width: 100px;
height: 100%;
position: absolute;
left: -100px;
top: 0;
background-color: green;
}
.banner:after {
left: 100%;
background-color: orange;
}
.content {
height: 300px;
padding: 10px;
background-color: #f1f1f1;
margin-top: 40px;
}
<header>
<div class="wrapper">
<div class="banner">Banner</div>
<div class="content">Content</div>
</div>
</header>

How to set CSS image width with respect to grandparent div

I am creating a "light box" sort of effect. Without using JavaScript, how can I make the light box resize according to the viewport size so that it always stays in the center of the viewport and occupy 80% of the width and height?
<div class="fullscreen-dim">
<div class="dialog">
<img src="http://placehold.it/300x200">
<a class="close-button" href="#">CLOSE</a>
</div>
</div>
.fullscreen-dim {
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0; right: 0;
width: 100%;
height: 100%;
}
img {
width: 100%;
height: 100%; // how to respect aspect ratio??
}
.dialog { // dialog should auto-size just big enough to wrap image
padding: 20px; // to create a "border" around the image;
position: fixed;
background-color: red;
left: 50%; top: 50%;
transform: translateX(-50%) translateY(-50%);
width: 80%;
height: 80%;
}
a {
position: absolute;
bottom: 5px; right: 5px;
}
In this method http://jsfiddle.net/3Lohtes9/ , the dialog resizes but the image does not respect aspect ratio.
This problem can also be interpreted as one of the "grandparent div" questions on SO. How can I set the image size with respect to full-screendim and let dialog to auto-size to fit?
EDIT: Instead of enclosing the img in the dialog div, I can achieve a similar visual effect of having the border around the image and still have the image resize accordingly when viewport size changes. However, I have no way to place the close button now. Any advice?
Change .dialog height from 80% to auto. See fiddle
.fullscreen-dim {
background-color: rgba(0, 0, 0, 0.7);
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
}
img {
width: 100%;
height: 100%;
}
.dialog {
padding: 20px;
// to create a"border" around the image;
position: fixed;
background-color: red;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
width: 80%;
height: auto;
}
a {
position: absolute;
bottom: 5px;
right: 5px;
}
edit:
try adding this if you want more control (like a min-height) or simply remove all height and width from .dialog:
width: auto;
max-width:80%;
height:auto;
max-height:80%;
min-height: 100px;
new fiddle
Using the information from this question, you can set the image to be aligned horizontally within the lightbox. Then by removing the height of the image, it will scale correctly with the aspect ratio.
The key CSS changes are here
img {
display: inline-block;
width: 100%;
vertical-align: middle;
}
/* This is a new element, see the question linked above. */
.helper {
display: inline-block;
height: 100%;
vertical-align: middle;
}
.dialog {
padding: 20px; // to create a "border" around the image;
position: fixed;
background-color: red;
left: 50%; top: 50%;
transform: translateX(-50%) translateY(-50%);
width: 80%;
height: 80%;
white-space: nowrap;
text-align: center; margin: 1em 0;
}
And the HTML
<div class="fullscreen-dim">
<div class="dialog">
<span class="helper"></span>
<img src="http://placehold.it/300x200"/>
<a class="close-button" href="#">CLOSE</a>
</div>
</div>
See fiddle: http://jsfiddle.net/3Lohtes9/7/
Instead of all of this
.dialog { // dialog should auto-size just big enought to wrap image
padding: 20px; // to create a "border" around the image;
position: fixed;
background-color: red;
left: 50%; top: 50%;
transform: translateX(-50%) translateY(-50%);
width: 80%;
height: 80%;
}
try
.dialog { // dialog should auto-size just big enought to wrap image
padding: 20px; // to create a "border" around the image;
position: fixed;
background-color: red;
left: 10%; top: 10%;
right: 10%; bottom: 10%
}

Resources