Image crop overlay - javascript

On an image upload page I have a preview of the image. I would like create an overlay that shows the image in a rectangle in the middle, with an opaque overlay around the outside of the rectangle.
Similar to this:
I am able to create a div overlay, but I need to reverse the opaque black background to be on the rest of the image but not on the rectangle. This way I can preview to the user what the final product will look like.
Here's what I have:
.wrapper {
position: relative;
height: fit-content;
width: fit-content;
display: flex;
}
.overlay {
max-width: 100%;
height: 100%;
aspect-ratio: 1 / 1.42;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
top: 0;
left: 150px;
border-radius: 0.5rem;
}
<div class="wrapper">
<img src="https://picsum.photos/500/300"/>
<div class="overlay"></div>
</div>
Requirements
I need to keep the aspect-ratio and relative size of the rectangle consistent.
No magic numbers or fixed width/height unless dynamically calculated per image, these images will be any size or dimensions and the layout needs to be responsive to (nearly) any screen size.
I can't change the markup too much because I'm working with the drag and drop api to move the rectangle within the image wrapper by changing its left and top positions.
I would like to use CSS or Javascript to solve this, not more HTML
Not looking to use object-fit: cover as I need the entire image visible in its native dimensions.

I hope the below code meets your requirements and solves your problem.
.wrapper {
position: relative;
height: fit-content;
width: fit-content;
display: flex;
}
.overlay {
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 0.5rem;
width: 100%;
overflow: hidden;
}
.overlay:before{
position: absolute;
content: '';
aspect-ratio: 1 / 1.42;
height: 100%;
top: 0;
left: 50%;
transform: translateX(-50%);
box-shadow: 0px 0px 0px 145px rgba(0, 0, 0, 0.4);
}
<div class="wrapper">
<img src="https://picsum.photos/500/300"/>
<div class="overlay"></div>
</div>

Related

css/JavaScript resize div content to fit window

I have a page with a lot of images positioned on top of another image.
The position of the smaller images is relative, and the left and top distance is given using px.
When I scale the window, the collection of images moves and stays in the right place. But I want it to also scale when I resize the window. (The ratio of the images should stay the same, but smaller/larger.)
All the images are contained in an overlaying div.
Is there any way for me to do this without having to reposition all the images? (I'm very new to css/JavaScript)
Here's an example of what is happening: https://codepen.io/gwenvere/pen/MWJdvJp
What I want is for the red ball to stay on top of the mountain, but for the mountain and ball to shrink if the window becomes smaller.
Here is an example of the css of one of the smaller images:
position: relative;
left: 161.7px;
top: 208.7px;
width: 79px;
height: 79px;
background-color: rgba(56, 152, 236, 0);
background-image: url('../images/Medium.png');
background-position: 0px 0px;
background-size: cover;
}
The css of the larger image:
.image-11 {
position: absolute;
left: 0%;
top: 148px;
right: 0%;
bottom: 0%;
width: 1200px;
max-width: 1200px;
margin-top: -37px;
margin-right: auto;
margin-left: auto;
}
css of the overlaying div:
.div-block-3 {
position: relative;
width: 1200px;
height: 800px;
max-height: none;
max-width: none;
min-height: auto;
min-width: auto;
margin-right: auto;
margin-left: auto;
background-color: rgba(83, 39, 39, 0);
-webkit-transform-origin: top left;
}
The image in your Codepen is set to position: absolute at a fixed width and height of 1200px and 800px, so it doesn’t resize.
As your description of your question talks about resizing the window, I’m assuming you want your main image to scale up and down and for the red dot to stay in the same relative position.
One way to do it using CSS would be to use percentages of the width and height to position the red dot, and use a percentage of the width to scale the size of the dot (using a ratio to set the dot’s height.
body {
padding: 0;
margin: 0;
}
.body {
position: relative;
width: 100%;
max-width: 1200px;
margin-top: 147px;
margin-right: auto;
margin-left: auto;
background-color: rgba(83, 39, 39, 0);
}
.largeImage {
width: 100%;
height: auto;
}
.smallImage {
display: block;
position: absolute;
left: 57.5%;
top: 26.17%;
width: 6.67%;
height: auto;
transform: translate(-50%,50%);
background-color: rgba(56, 152, 236, 0);
background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Circle_Burgundy_Solid.svg/1024px-Circle_Burgundy_Solid.svg.png");
background-position: 0px 0px;
background-size: cover;
margin: 0 auto;
}
.smallImage::before {
display: block;
padding-top: 100%;
content: "";
}
.smallImage a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<div class="body">
<img src="https://media.sproutsocial.com/uploads/2017/02/10x-featured-social-media-image-size.png" loading="lazy" alt="" class="largeImage">
<div class="smallImage">
</div>
</div>
I included a margin above the image as you had that in your Codepen.

Scrollable page with percent-width navbar

Goal: create scrolling content overlaid by an equally wide navbar. Example html could look like:
<div class="scrollable">
<div class="content"></div>
</div>
<div class="navbar"></div>
Criteria:
.content fills a percent width of .scrollable, and is horizontally centered
.scrollable should have scrollbars
.navbar is exactly as wide as .content, centered exactly atop .content
Scrollbar width should be treated as unknown
Avoid javascript running via scroll, requestAnimationFrame, setInterval, etc. Ideally no js.
The most intuitive approach fails since the scrollbar causes a discrepancy in dimensions:
.container {
position: absolute;
width: 80%; height: 80%; left: 10%; top: 10%;
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.3);
}
.scrollable {
position: absolute;
width: 100%; height: 100%; left: 0; top: 0;
overflow: hidden visible;
}
.scrollable > .content {
width: 80%; margin: 60px auto;
background-color: rgba(0, 0, 0, 0.2); text-align: center;
}
.navbar {
position: absolute;
left: 10%; bottom: 0; width: 80%; height: 50px;
background-color: rgba(255, 0, 0, 0.3); color: rgba(255, 255, 255, 1);
}
<div class="container">
<div class="scrollable">
<div class="content">abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/>abcd<br/><br/><br/></div>
</div>
<div class="navbar">I am navbar</div>
</div>
The issue here is that .content takes up a percentage width of .scrollable's width minus its scrollbar width, whereas .navbar is set to a percentage width of .scrollable including its scrollbar width.
What is the best way to get around this discrepancy?
check the answer in the codepen : https://codepen.io/the-wrong-guy/pen/vYLzRZZ
And you should use position: fixed instead of position: absolute to fix the navbar at the top

How can I create a circle with elements at the very end of its axis?

I'll be using some SVGs that will be those avatars on the axis. For now all I need is a hint on how to set those avatars at the very end of every axis.
I am trying to achieve this:
This the code I have so far:
body {
background-color: #de4e40;
text-align: center;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
margin: 0;
display: flex;
}
.squareLoader {
height: 200px;
width: 200px;
background-color: white;
border: 1px solid black;
border-radius: 50%;
}
<div class='squareLoader'></div>
And here is a codepen in case you want to take a look.
Is there any guide or someone can help me on how to achieve this?
I can use flexbox and also I am using React Native. Just in case.
Make squareLoader a relative parent
Position element in corners using translate, top, left
Share styles wherever possible
Store repeated offset value in CSS variable
:root {
--offset: -1.4em;
}
body {
background-color: #de4e40;
text-align: center;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
margin: 0;
display: flex;
}
.squareLoader {
height: 200px;
width: 200px;
background-color: white;
border: 1px solid black;
border-radius: 50%;
position: relative;
}
.squareLoader img {
position: absolute;
width: 50px;
}
.one, .three {
left: 50%;
transform: translateX(-50%);
}
.two, .four {
top: 50%;
transform: translateY(-50%);
}
.one {
top: var(--offset);
}
.two {
right: var(--offset);
}
.three {
bottom: var(--offset);
}
.four {
left: var(--offset);
}
<div class="squareLoader">
<img src="https://image.flaticon.com/icons/svg/190/190675.svg" alt="" class="one">
<img src="https://image.flaticon.com/icons/svg/190/190675.svg" alt="" class="two">
<img src="https://image.flaticon.com/icons/svg/190/190675.svg" alt="" class="three">
<img src="https://image.flaticon.com/icons/svg/190/190675.svg" alt="" class="four">
</div>
https://jsfiddle.net/uf2t5p6r/3/
If I understand your post correctly, you want to place SVG images on the North, South, East, and West points of a circle with CSS; It is definitely possible to do this with CSS, but it depends completely on the size of the container and the size of the images being used.
The example circle you provided has a set height and width, so assuming that your SVG images are also a set size and do not change with page size you can do something like this.
body {
background-color: #de4e40;
text-align: center;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
margin: 0;
display: flex;
}
.squareLoader {
/* added 'position: relative', because parent elements of absolute positioned elements have to be positioned to prevent mayhem */
position: relative;
height: 200px;
width: 200px;
background-color: white;
border: 1px solid black;
border-radius: 50%;
}
.avatar {
position: absolute;
left: 75px;
top: 75px;
border: 1px solid black;
height: 50px;
width: 50px;
}
.avatarN {
top: -25px;
}
.avatarS {
top: 175px;
}
.avatarE {
left: 175px;
}
.avatarW {
left: -25px;
}
and the HTML with .avatar <div>s (you can stick the SVG images inside these divs):
<div class='squareLoader'>
<div class="avatar avatarN"></div>
<div class="avatar avatarS"></div>
<div class="avatar avatarE"></div>
<div class="avatar avatarW"></div>
</div>
In the previous example all four avatar <div>s are given a height and width of 50px.
.avatarN has a top position of -25px because that is half of the image's height and a left position of 75px (half of .squareLoader's width minus half of the image's width).
.avatarW has a top position of 75px (half of .squareLoader's height minus half of the image's height) and a left position of 25px, which is half of the image's height.
And so on for the other divs.
If you are going to make your .squareLoader <div> resize based on the page size, and the images resize based on page size, you can use the calc() CSS function which can be used anywhere a length unit is allowed in CSS.
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
w3Schools has a pretty decent cursory explanation of all the units allowed in CSS:
https://www.w3schools.com/cssref/css_units.asp
And also, here's their page on position values in CSS as well:
https://www.w3schools.com/cssref/pr_class_position.asp
Whether or not you are using flexbox, you'll still have to use the position property to get the images where you want them.
One idea to create this is to consider only background and it will be easier to handle:
body {
background-color: #de4e40;
text-align: center;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
margin: 0;
display: flex;
}
.squareLoader {
height: 250px;
width: 250px;
background:
url(https://picsum.photos/50/50?image=1069) top center,
url(https://picsum.photos/50/50?image=1069) bottom center,
url(https://picsum.photos/50/50?image=1069) left center,
url(https://picsum.photos/50/50?image=1069) right center,
/*the circle*/
radial-gradient(farthest-side,
#fff calc(100% - 32px),#000 calc(100% - 30px),
#000 calc(100% - 30px),#000 calc(100% - 20px),
transparent calc(100% - 18px));
background-repeat:no-repeat;
}
<div class='squareLoader'></div>

Calculate left css value for skewed div

I have a wiper div which I want to use to wipe diagonally through a parent div.
The wiper div has the following class:
.wiper {
position: absolute;
height: 100%;
top: 0;
left: 0;
background-color: orange;
transform: skew(45deg);
}
I want the wiper to start offscreen to the right, and end offscreen to the left.
When the wiper is halfways, the screen must be completely filled by the wiper.
The problem is, I don't know how big the wipers parent is. So I need to calculate the following:
Width: How wide in percent must the wiper be, to fill the screen when it is halfway.
Startleft: What should the starting left property be in percent, for the wiper to be just offscreen right.
Endleft: What should the ending left property be, for the wiper to be just offscreen left.
Here is an example in jsfiddle, but with hardcoded values. I just don't know how to calculate the relative values, when dealing with a skewed div.
http://jsfiddle.net/jpg850kx/22/
I would do something differently using gradient where you don't need complex calculation:
body,
html {
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: hidden;
padding: 20px;
}
#wrapper {
width: 60%;
height: 100%;
position: relative;
overflow: hidden;
}
.content {
width: 100%;
height: 100%;
color: white;
display: flex;
justify-content: center;
align-items: center;
background-color: black;
}
.wiper {
position: absolute;
height: 200%;
width: 400%;
top: 0;
left: 100%;
z-index:1;
background-image:
linear-gradient(to bottom left,orange 49.5%,transparent 50%),
linear-gradient(to top right,orange 49.5%,transparent 50%);
background-size:50.1% 100%;
background-repeat:no-repeat;
background-position:left,right;
transition:all 3s;
}
#wrapper:hover .wiper{
left:-300%;
}
<div id="wrapper">
<div class="content">
Old content
</div>
<div class="wiper"></div>
</div>

How to center a div in the middle of a background image with size contain?

I have a background image with size set to contain:
background: url('https://cdn.sstatic.net/Sites/stackoverflow/img/404.svg') no-repeat center center;
background-size: contain;
And I have a div that I always want it to be in the center of the background image
<div class="bg">
<div class="center"></div>
</div>
Is there a way to keep the .center div in the center of the background image at all times? With CSS and/or JavaScript?
Or some other way to make an image responsive and have a div on the center at all times?
Code pen example https://codepen.io/brunolm/pen/GQxRVP
I think that's not possible, there is no way to retrieve the size on the background image resized by a modifier like contain.
Responsive Image solution
Codepen
Code https://codepen.io/brunolm/pen/rJdaGG?editors=1111
Full View https://codepen.io/brunolm/full/rJdaGG/
So I decided to try to put the image with a position: absolute and the div I want to center also with an absolute positioning.
Container
I can center elements by styling it with
align-items: center;
bottom: 0;
display: flex;
height: 100%;
justify-content: center;
left: 0;
position: relative;
right: 0;
top: 0;
Image
I can make the image responsive using
max-height: 100%;
max-width: 100%;
I can make it behave like a background by disabling selection
user-select: none;
I can center it with
bottom: 0;
margin: auto;
position: absolute;
top: 0;
Centered div
I can center it with
position: absolute;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
Calculate size
And to calculate the div size to be centered on the image
function doResize() {
const img = document.getElementById('img');
const center = document.getElementById('center');
// img is responsive and width/height is available
center.style.width = `${img.width * 0.5}px`;
center.style.height = `${img.height * 0.65}px`;
console.log(img.width, 'x', img.height);
}
// recalculate whenever the window size changes
window.addEventListener('resize', doResize);
// calculate initial size
doResize();
display: flex;, align-items: center; and margin: 0 auto; are the keywords here.
To make the div high as the bg img is, use this example: https://codepen.io/phng/pen/PWEJGO. And then you could use position: absolute; to negate the padding on your second div.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ufo {
background: url('https://cdn.sstatic.net/Sites/stackoverflow/img/404.svg') no-repeat center;
display: flex;
align-items: center;
border: 1px solid #000;
width: 500px;
height: 500px;
}
.ufo div {
width: 150px;
height: 150px;
background-color: steelblue;
margin: 0 auto;
}
<div class="ufo">
<div>
</div>
</div>

Categories