I am trying to make a 50% rounded img inside a simple div. I have tried 2 ways to do it, but obviously neither has worked for me.
If it makes something clear, the image, that I'm getting is square
/*HTML*/
<div class="img-container"></div>
/*CSS*/
.img-container {
background: url("../../../../../assets/img/user-photo.svg") no-repeat center top / cover;
height: 125px;
width: 125px;
border-radius: 50%;
}
/*HTML*/
<div class="img-container">
<img src="path_to_img" alt="User photo">
</div>
/*CSS*/
.img-container {
width: 125px;
height: 125px;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
I am getting it quite cropped in the bottom.
Are there any other solutions or what I am doing wrong in 2 examples above? Any help appreciate.
This is some simple markup, a div container and the image is enough.
If the image may come in different sizes or shapes, you can use the object-fit property to make sure it displays correctly regardless. Just make sure you define the explicit size (height and width) you need the image to be, and then you can use object-fit: cover on the img itself so it maintains its aspect ratio and uses all available space for exmaple.
.img-container {
background-color: purple;
padding: 10px 0;
width: 200px;
}
img {
border-radius: 50%;
width: 100px;
height: 100px;
display: block;
margin: 0 auto;
}
img.rect-img {
object-fit: cover;
}
<div class="img-container">
<img src="https://via.placeholder.com/100" alt="User photo">
</div>
<div class="img-container">
<img class="rect-img" src="https://via.placeholder.com/100x50" alt="User photo">
</div>
It works without any problem. I think your image has some transparent parts.
img {
box-shadow: 2px 2px 5px rgba(0, 0, 0, .4);
}
img.a {
width: 64px;
border-radius: 100%;
}
img.b {
width: 64px;
border-radius: 100%;
object-fit: cover;
width: 64px;
height: 64px;
}
<h1>Non-square image:</h1>
<img class="a" src="https://images.unsplash.com/photo-1579075475207-e59cd9d39be8">
<hr>
<h1>Converted to square using CSS:
<h1/>
<img class="b" src="https://images.unsplash.com/photo-1579075475207-e59cd9d39be8">
Related
Here is my html and css code:
.image-box{
max-width: 300px;
position: relative;
}
.image-box img{
max-width: 100%;
width: 100%;
object-fit: cover;
border: 8px solid #000000;
border-right: 0;
border-bottom: 0;
/* border-image: linear-gradient(to right, #000 68%, transparent 32%) 100% 1; */
}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300" alt="">
</figure>
</div>
While running this, I receive this.
But, I want to have something like this:
If I uncomment this line
border-image: linear-gradient(to right, #000 68%, transparent 32%) 100% 1;
Then it shows half width border on top, but this also make the left border disappear and show like this.
You can do something like this using pseudo classes to make the border at the top like how you want it to be achieved:
What it does is hide the half of the border at the top.
.box {
width: 150px;
height: 150px;
background-color: black;
border-top: 5px solid red;
border-left: 5px solid red;
position: relative;
}
.box:after {
content: "";
width: 50%;
height: 5px;
background-color: white;
position: absolute;
right: 0;
top: -5px;
}
<div class="box"></div>
Disclaimer: Not an exhaustive list. Try to come up with yet another solution!
With background-image: linear-gradient()
To make a linear-gradient look like a border, we can add padding to the image and a hard color-stop to the gradient:
.image-box {
--thickness: 8px;
}
.image-box img {
padding-top: var(--thickness);
padding-left: var(--thickness);
background-image: linear-gradient(to right, black 60%, white 60%);
}
figure{margin:0;line-height:0}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
A potential problem with this is that only one side of the border may be shorter.
With Pseudo-elements
Pseudo-elements can be used for presentational styling. You can easily identify them in your CSS by their double-colons (e.g. ::before, ::marker).
Sidenote: While still supported for legacy reasons, they can also be written with a single-colon (e.g. :before). Do yourself a favour and use the double-colons.
We can use pseudo-elements to create the border.
I will use custom properties to make the code easier to change.
Personally, I enjoy the method Placing behind the most, because that way no bleeding through of the parent's background should happen in extreme (zoom) cases.
Composition
Composite the border with ::before for the left and ::after for the top side. Since these are separate elements, we can define their width and height individually:
.image-box::before, .image-box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: black;
}
.image-box::before { /* Left */
width: var(--thickness);
height: 100%;
}
.image-box::after { /* Top */
width: 60%;
height: var(--thickness);
}
.image-box {
--thickness: 8px;
position: relative;
/* Leave space for border */
padding-top: var(--thickness);
padding-left: var(--thickness);
max-width: 300px;
box-sizing: border-box;
}
.image-box img {max-width:100%}
figure{margin:0;line-height:0}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Placing behind
Place the image on top of a pseudo-element to make it look like a (partially wide) border:
.image-box::before, .image-box>figure {
grid-area: 1/1 / 1/1; /* Place both on first grid-cell */
}
.image-box::before {
content: "";
width: 60%;
height: 100%;
background-color: black;
}
.image-box {
--thickness: 8px;
max-width: 300px;
display: grid;
}
.image-box img {
/* Leave space for border */
padding-top: var(--thickness);
padding-left: var(--thickness);
width: 100%;
box-sizing: border-box;
}
figure{margin:0;line-height:0}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Using clip-path: polygon()
Specify each point of the "top-left corner" shape in polygon():
.image-box {
position: relative;
padding-top: 8px;
padding-left: 8px;
max-width:300px;
}
.image-box::before {
--thickness: 8px;
content: "";
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
clip-path: polygon(
0 0,
100% 0,
100% var(--thickness),
var(--thickness) var(--thickness),
var(--thickness) 100%,
0 100%);
background-color: black;
}
figure {margin:0;line-height:0}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Why not use border?
Edit: Apparently border-image is a thing. See an example. Bottom section is therefore outdated.
Unfortunately, each side of a border can only be a single color. This means the black & white top border is not possible by only using the border property.
A solution to this would be to redraw over part of the border that we don't want:
#example {
padding: 1rem;
background-color: slateblue;
}
.image-box {
--thickness: 8px;
position: relative;
border: 0 solid black;
border-top-width: var(--thickness);
border-left-width: var(--thickness);
max-width: 300px;
}
.image-box::after {
content: "";
position: absolute;
top: calc(-1 * var(--thickness));
right: 0;
/* 100% - <length> + <thickness left-side> */
width: calc(100% - 60% + var(--thickness));
height: var(--thickness);
background-color: white;
}
body {
display: flex;
flex-direction: column;
gap: 1rem;
}
figure{margin:0;line-height:0}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
<div id="example">
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
</div>
But as you can see, this way we will lose the background of the parent. Hard-coding some color only works if the parent's background is a solid color. If the parent's background is an image, this won't work.
Also, having to tell .image-box the color to draw over with is redundant information (because the background already exists) and would only cause more mental overhead for the developer.
you are almost good with border-image. You need to correctly define the slice.
.image-box {
max-width: 300px;
position: relative;
}
.image-box img {
max-width: 100%;
width: 100%;
object-fit: cover;
border: 8px solid #000000;
border-right: 0;
border-bottom: 0;
border-image: linear-gradient(to right, #000 68%, transparent 32%) 1;
}
<div class="image-box">
<figure>
<img src="https://via.placeholder.com/300" alt="">
</figure>
</div>
I have a card with an image header. When on hover of the card, I'd like to change the non-image part background color. Code as follows:
.card {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.3s;
width: 40%;
height: 500px;
}
.card-image {
display: block;
position: relative;
}
.card:hover {
background-color: grey;
}
img {
display: block;
width: 100%;
height: 200px;
background-size: cover;
}
.container {
padding: 0 16px;
}
<div class="card">
<div class="card-image">
<img style="background-image: url(https://www.w3schools.com/howto/img_avatar.png);">
</div>
<div class="container">
<h4><b>John Doe</b></h4>
<p>Architect & Engineer</p>
</div>
</div>
I use a background image as the image here because I need the background-size: cover effect, but as hovering on the card, you can see a border being added to the image due to it's actually a background image, I wonder how I can get rid of the border?
EDIT: the border isn't that obvious:
You are using background-image attribute, you should use the style on a <div> tag instead (or any other tag you with display:block), since this is an a background image not an image, I think this is caused by default browser behavior for not providing src attribute, which would be considered as 404 error for the image, not sure if this is the case here, here is a working snippet:
.card {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.3s;
width: 40%;
height: 500px;
}
.card-image {
display: block;
position: relative;
}
.card:hover {
background-color: grey;
}
.img {
display: block;
width: 100%;
height: 200px;
background-size: cover;
background-image: url(https://www.w3schools.com/howto/img_avatar.png);
}
.container {
padding: 0 16px;
}
<div class="card">
<div class="card-image">
<div class="img"></div>
</div>
<div class="container">
<h4><b>John Doe</b></h4>
<p>Architect & Engineer</p>
</div>
</div>
The problem is that you're using the img HTML element with a background-image CSS declaration. Two possible solutions:
1) Keep the img element, add a src attribute, and use the object-fit declaration.
HTML:
<div class="card-image">
<img src="https://www.w3schools.com/howto/img_avatar.png">
</div>
CSS:
img {
display: block;
width: 100%;
height: 200px;
object-fit: cover;
}
2) Remove the img element (and declaration) and apply the background-image declaration to the .card-image element.
HTML:
<div class="card-image"></div>
CSS:
.card-image {
background-image: url("https://www.w3schools.com/howto/img_avatar.png");
background-size: cover;
height: 200px;
}
I want to display images in my div. I display different images according to the condition (if moviePoster true).
I moviePoster I display it, but if it is false, I display a image that informed that the file is not found.
I don't know why but when I display these 2 types of image, the moviePoster image, exceeding the size of the dive.
This is a screen from the issue in my application
.list {
border: 1px solid grey;
display: flex;
margin: 30px;
height: 230px;
border-radius: 10px;
box-shadow: 1px 1px 12px #555;
}
.list-img {
// border: 5px solid red;
width: 20%;
}
img {
height: 100%;
width: 100%;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
<div class="list">
<div class="list-img">
<div *ngIf="moviePoster; else notFound">
<img src="https://image.tmdb.org/t/p/w200/{{moviePoster}}" alt="...">
</div>
<ng-template #notFound>
<img src="../../assets/not_found.jpg" alt="...">
</ng-template>
</div>
img is a default display: inline, so height and width refers to inner content.
Anyway set image width and height usually stretches image, and that's orrible.
I suggest on using a div with the image setted as background, so use something like that:
html:
...
<div
*ngif="..."
class="thumbnail"
style="background-image: url(https://...{{ moviePoster }})"
></div>
...
css:
.thumbnail{
background-size: cover;
background-position: center;
}
You should apply this class also to #notFound.
One thing missing: thumbnail div must have height and width expressed
You can do that in multiple ways via css, depending on how have you structured the card box.
Hope it helps.
i think this is what you want :
if the image is null then the default background will show.
UPDATE: i have made it more dynamic
.list {
display: flex;
flex-direction: column;
}
.list-item {
height: 150px;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 0 3px 2px rgba(0,0,0,.5);
}
.list-item + .list-item {
margin-top: 10px;
}
.list-img {
width: 200px;
height: 150px;
transition: background .5s ease;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
background-image: url(https://www.tourismselangor.my/wp-content/themes/Directory/images/noimage.jpg);
}
<div class="list">
<div class="list-item">
<div class="list-img" style="background-image: url(https://picsum.photos/200)"></div>
</div>
<div class="list-item">
<div class="list-img"></div>
</div>
<div class="list-item">
<div class="list-img" style="background-image: url(https://picsum.photos/200)"></div>
</div>
</div>
I'm working on my first website. I've created a big image banner and it's working but I have a problem with setting his height. When I try to do this with % height my banner disappears. I would like to make it responsive and make it shorter when the window is small. Here is my code and CSS styles for container div:
#slides-container
{
width: 100%;
height: 400px;
margin: 0 auto;
position: relative;
}
#slides-container>img
{
width: 100%;
height: 100%;
position: absolute;
max-width: 100%
}
#slides-container>.arrow-button
{
position: absolute;
width: 50px;
height: 50px;
border: none;
border-radius: 25px;
top: 200px;
background: none;
color: white;
font-size: 20px;
}
#slides-container>#button-next:hover
{
box-shadow: 10px 0px 20px 0px black;
}
#slides-container>#button-previous:hover
{
box-shadow: -10px 0px 20px 0px black;
}
#slides-container>#button-previous
{
position: relative;
float: right;
}
.slide-fade
{
animation-name: fade;
animation-duration: 0.2s;
}
#keyframes fade
{
from{opacity: 0.4}
to{opacity: 1}
}
<div id="slides-container">
<img class="slides slide-fade img-responsive" src="img/1.jpg"/>
<img class="slides slide-fade img-responsive" src="img/2.jpg"/>
<img class="slides slide-fade img-responsive" src="img/3.jpg"/>
<img class="slides slide-fade img-responsive" src="img/4.jpg"/>
<img class="slides slide-fade img-responsive" src="img/5.jpg"/>
<button class="arrow-button" onclick="plusIndex(-1)" id="button-next">❮</button>
<button class="arrow-button" onclick="plusIndex(1)" id="button-previous">❯</button>
</div>
You can use vh instead of %. It is the other way to make the height responsive in every view height. Relative to 1% of the height of the viewport*
The overlay image in the example below is supposed to stay at the same location relative to the larger image independent of the size of the container.
I added 2 examples below of the "img_overlay" CSS module, one where it is inside a portrait test container (green), and another inside a green landscape container. It works fine for portrait, but not for landscape, because the "img_overlay__container" (red) extends to the whole width of the parent container instead of being limited to the width of the black image. If the red container would be as wide as the black image then everything would be OK.
I can make it work for landscape too with a simple inline-block, but then it breaks for portrait.
Mind that the image should be flexible, expanding and shrinking according to the available space, up to its natural size, so no fixed size solutions please. And the overlay image should retain its size ratio in relation to the black image (25% of the black image), so that it looks the same independent of screen size.
I should add that I am testing on Chrome Version 59.0.3071.115 (Official Build)
(64-bit)
Am I missing something or is it simply not possible with current CSS3?
Edit (14/07/2017): I made the containers resizable so its easier to test.
https://jsfiddle.net/rvmxpwq1/3/
$( ".test" ).resizable();
body {
margin-bottom: 100vh;
}
.img_overlay {
display: inline-flex;
max-height: 100%;
}
.img_overlay__container {
position: relative;
background-color: rgb(255, 0, 0);
}
.img_overlay__img {
border-radius: 50%;
max-height: 100%;
max-width: 100%;
}
.img_overlay__overlay {
border-radius: 50%;
max-width: 25%;
max-height: 25%;
position: absolute;
right: 0px;
bottom: 0px;
}
.test {
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(0, 255, 0);
border: 3px solid rgb(0, 255, 0);
}
.test--1 {
width: 200px;
height: 300px;
}
.test--2 {
width: 300px;
height: 200px;
}
.test--3 {
width: 500px;
height: 500px;
}
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
Portrait container (300x200): <strong>works</strong>, this is how it should always look at any container size.
<div class="test test--1">
<div class="img_overlay">
<div class="img_overlay__container">
<img class="img_overlay__img" src="https://dummyimage.com/400x400/000/ffffff.jpg&text=Image">
<img class="img_overlay__overlay" src="https://dummyimage.com/100x100/0000ff/ffffff.jpg&text=Overlay">
</div>
</div>
</div>
<br> Landscape container (200x300): <strong>does not work</strong>, because the overlay is not next to the image.
<div class="test test--2">
<div class="img_overlay">
<div class="img_overlay__container">
<img class="img_overlay__img" src="https://dummyimage.com/400x400/000/ffffff.jpg&text=Image">
<img class="img_overlay__overlay" src="https://dummyimage.com/100x100/0000ff/ffffff.jpg&text=Overlay">
</div>
</div>
</div>
<br> Large container (500x500): <strong>works</strong>, the images are not enlarged above their natural size.
<div class="test test--3">
<div class="img_overlay">
<div class="img_overlay__container">
<img class="img_overlay__img" src="https://dummyimage.com/400x400/000/ffffff.jpg&text=Image">
<img class="img_overlay__overlay" src="https://dummyimage.com/100x100/0000ff/ffffff.jpg&text=Overlay">
</div>
</div>
</div>
How about now?
here is a fiddle:
https://jsfiddle.net/f9e2gkpk/5/
.wrapper{
max-height: 100%;
max-width: 100%;
}
.img_overlay {
display: inline-flex;
max-height: 100%;
}
.img_overlay__container {
position: relative;
background-color: rgb(255, 0, 0)
}
.img_overlay__img {
border-radius: 50%;
max-height: 100vh;
max-width: 100%;
}
.img_overlay__overlay {
border-radius: 50%;
width: 25%;
position: absolute;
right: 0px;
bottom: 0px;
}
.test {
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(0, 255, 0);
border: 3px solid rgb(0, 255, 0);
height: 100vh;
}
<div class="test test--2">
<div class="img_overlay">
<div class="img_overlay__container">
<div class="wrapper">
<img class="img_overlay__img" src="https://dummyimage.com/400x400/000/ffffff.jpg&text=Image">
<img class="img_overlay__overlay" src="https://dummyimage.com/100x100/0000ff/ffffff.jpg&text=Overlay">
</div>
</div>
</div>
</div>