On my website a banner image has a certain height (responsive) but it has an overlay (#vignette) which is nested inside an a-tag together with the banner image. #vignette gets its height from its parent:
#vignette {
box-shadow: inset 0 0 50px 4px rgba(0,0,0,0.35), inset 0 10px 10px rgba(0,0,0,0.05);
position: absolute;
display: block;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
And the a-tag adjust its height to its content:
a#banner-image {
display: block;
position: relative;
width: auto;
height: auto;
}
How then is it possible that the a-tag is taller than the image itself? Can't seem to solve this. Thanks.
Ensure the img is displayed as a block element.
a#banner-image img {
display: block;
}
As #Ianzz correctly states, this is because of an issue with descender space for all inline elements.
Related
I have a piece of html/css that represents a button with a border.
The button has pseudo elements which overlay the button - the simple example shows one of them.
The pseudo element is taller than the original element (height set using px) but the same width (set at 100%).
There are two issues which aren't working as I expect in the current design:
Despite using box-sizing: border-box, the pseudo width does not
include the border.
The pseudo element is positioned absolutely (top, left) but this
reference position is inside the parent border.
This seems to be the same in both Chrome and Edge which would indicate I'm not doing something right - however, I'm particularly confused with regard to box-sizing.
.container {
padding: 50px;
}
.button {
border: solid 4px red;
box-sizing: border-box;
display: inline-flex;
justify-content: center;
align-items: center;
height: 36px;
padding: 0 16px;
position: relative;
z-index: 1;
}
.button::before {
background-color: rgba(76, 255, 0, 0.8);
box-sizing: inherit;
content: "";
display: block;
position: absolute;
top: -4px;
left: 0;
height: 44px;
width: 100%;
z-index: -1;
}
<div class="container">
<a class="button">Button</a>
</div>
From the specification
The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:
....
If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:
In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.1, if the inline element is split across multiple lines, the containing block is undefined.
Otherwise, the containing block is formed by the padding edge of the ancestor
Then
The padding edge surrounds the box padding. If the padding has 0 width, the padding edge is the same as the content edge. The four padding edges define the box's padding box.
This explain why your element doesn't use the border-box as reference but the padding-box when positionned. It's also the same for percentage width1. using width:100% means the padding and the content of the containing block. Border aren't counted.
Concerning box-sizing
... , any padding or border specified on the element is laid out and drawn inside this specified width and height.
So the border need to belong to the element not a parent element in order to consider box-sizing which is not your case since the border isn't applied to the pseudo element:
1 For absolutely positioned elements whose containing block is based on a block container element, the percentage is calculated with respect to the width of the padding box of that element.ref
.box {
border:5px solid;
padding:10px;
background:red;
min-height:100px;
position:relative;
}
span:first-child {
display:inline-block;
width:100%;
background:blue;
}
span:last-child {
position:absolute;
bottom:0;
left:0;
width:100%;
background:green;
}
<div class="box">
<span>I am a static element</span>
<span>I am a absolute element</span>
</div>
An idea to obtain what you want is to use inset box-shadow instead of border:
.container {
padding: 50px;
}
.button {
box-shadow: inset 0 0 0 4px red;
box-sizing: border-box;
display: inline-flex;
justify-content: center;
align-items: center;
height: 36px;
padding: 0 16px;
position: relative;
z-index: 1;
}
.button::before {
background-color: rgba(76, 255, 0, 0.8);
box-sizing: inherit;
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: -1;
}
<div class="container">
<a class="button">Button</a>
</div>
Try increasing the width of the pseudoelement with the size of the border of the parent and shift it to the left with left: -4px:
.container {
padding: 50px;
}
.button {
border: solid 4px red;
box-sizing: border-box;
display: inline-flex;
justify-content: center;
align-items: center;
height: 36px;
padding: 0 16px;
position: relative;
z-index: 1;
}
.button::before {
background-color: rgba(76, 255, 0, 0.8);
box-sizing: inherit;
content: "";
display: block;
position: absolute;
top: -4px;
left: -4px;
height: 44px;
width: calc(100% + 8px);
z-index: -1;
}
<div class="container">
<a class="button">Button</a>
</div>
Im 3 years late but Ive found a solution to this.
Credits to https://www.getpeblo.com I saw this implemented on their site first. Also thanks to user Temani Afif for clearing it up that the absolutely positioned pseudo element will get the width of its parent's padding box and not border box.
So to get around this you need to wrap the button in which you have set a border in a div container. This div has to have a display of inline block so its width will be the full width of the button(Note that if your container is a grid or flex child of a grid/flex container I think it sort of behaves like an inline block but id still suggest to set the display to inline-block anyway).
Now you want the pseudo element to be a descendant of the container and not the button itself so it gets the full width of the button as the container's padding box is the same width as the button's border box. Here's the snippet:
/* UNRELATED STYLES*/
*{
margin: 0;
padding: 0;
border:0;
box-sizing: border-box;
}
*::after{
box-sizing:border-box;
}
body{
font-family: "Helvetica", "sans-serif";
line-height: 1;
font-weight:400;
}
.container{
max-width:900px;
min-height:100vh;
margin: 0 auto;
display:grid;
place-items:center;
}
/* Fix */
.btn-contain{
position:relative;
display:inline-block;
}
.btn-contain::after{
content: "";
position: absolute;
top:2px;
left:2px;
height: 100%;
width: 100%;
border-radius: 4px;
background-color: #34344B;
z-index: -1;
}
.btn:any-link{
display: inline-block;
text-decoration: none;
padding: 12px 30px;
border: 2px solid #34344B;
border-radius: 4px;
font-size: 18px;
font-weight: 600;
background-color: #F031A7;
color: #34344B;
transition: 300ms;
}
<div class="container">
<div class="btn-contain">
<a class="btn" href="#">Im a button</a>
</div>
</div>
I want the inner shadow of my div to come over it's content (please note that I don't simply want the image to have an inner shadow, I have a much more complicated scrollable div with so many children this is just a minimal example.
div {
white-space: nowrap;
box-shadow: inset 0 0 10px #000000;
}
img {
display: block;
}
<div>
<img src="http://www.claireking.com/wp-content/uploads/2018/01/images.png" />
</div>
Agree with Vitalii Chmovzh answer, but in case you don't want any space by padding.
So just use this for your img tag.
img{
display: block;
position:relative;
z-index:-1;
}
Without changing sizes of your box model.
Updated fiddle
Just add padding for a shadow amount.
div {
white-space: nowrap;
box-shadow: inset 0 0 10px #000000;
padding: 10px;
}
See working fiddle:
https://jsfiddle.net/f0qasdo6/
UPD: Another working example without changing div size:
div {
white-space: nowrap;
position: relative;
}
div:before {
content: '';
display: block;
position: absolute;
top:0;
left: 0;
right: 0;
bottom: 0;
box-shadow: inset 0 0 10px #000000;
}
Downside of this approach is that you will not be able to click on the content inside the div, so it can be used to add an effect to non-interactible blocks.
See fiddle:
https://jsfiddle.net/r3t2p2cw/
The issue with this is that the image gets rendered over the shadow.
Try this,
div {
white-space: nowrap;
position: relative;
}
img{
display: block;
}
div::before {
box-shadow: inset 0 0 10px #000000;
position: absolute;
width: 100%;
height: 100%;
content: "";
}
Somehow your image doesn't work for me. Here is the solution:
div {
width: 70%;
white-space: nowrap;
box-shadow: inset 0 0 10px #000000;
}
img{
width: 100%;
display: block;
position: relative;
z-index: -1;
}
https://jsfiddle.net/tp9pz9w0/7/
How to make a fixed positioned div fit its content width?
I've made a demo here
Before clicking on the Load button, the div must only have enough width to contain the gif image and the button.
When more content is loaded, the width of the div must fit its width.
here is the CSS I've made
body{background: #eee; }
#divToCenter{
border-radius: 5px;
box-shadow: 0 0 0 10px rgba(0,0,0,0.2);
background: #fff;
padding: 20px;
position: fixed;
top: 20px;
right: 0;
left: 0;
margin-right: auto;
margin-left: auto;
max-width: 400px;
}
Since you are using JavaScript/jQuery to show/hide the loader, why don't you change the width of the box via JavaScript?
You could simply toggle a class called .wide for instance, to achieve the desired result as follows:
EXAMPLE HERE
CSS:
#divToCenter{
/* other declarations... */
text-align: center;
width: 50px;
}
#divToCenter.wide {
width: 400px;
text-align: left;
}
jQuery:
var $divToCenter = $("#divToCenter");
$("#show-more-data").click(function() {
// ...
$divToCenter.addClass("wide");
});
$("#show-less-data").click(function() {
// ...
$divToCenter.removeClass("wide");
});
Add display: table, position: relative and margin:0 auto to the following element:
#divToCenter{
border-radius: 5px;
box-shadow: 0 0 0 10px rgba(0,0,0,0.2);
background: #fff;
padding: 20px;
display: table;/*Add this*/
position: relative;/*Change fixed with relative*/
top: 20px;
margin:0 auto;/*Add this*/
max-width: 400px;
}
fiddle
I am trying to center a triangle in the exact center of a div, but i cant do it.
It positions itself in the middle of the div but just on horizontal alignment not vertical
.I made the margin: 0 auto; but still doesn't work.I have also tried display: table;
margin: 0 auto; on the inner div giving a margin: 0 auto; to outside div ,yet nothing.I also tried with display: inline-block; and no result. And i don't know why! Does someone have any idea?
My simple code is :
jsfiddle.net/
There are few options.
My favourite is to give outer div an absolute position, give the inner one a relative position and then use top:50% to position vertically. You also need to add a negative margin of half the height of the triangle because top:50% will centre the top of the triangle not the middle of it.
#main_content {
width: 300px;
height: 300px;
background-color: red;
position: absolute;
}
#container {
width: 0px;
height: 0px;
border-style: solid;
border-width: 25px 43.3px 25px 0;
border-color: transparent #007bff transparent transparent;
position: relative;
top:50%;
margin: -21.65px auto; //Half the height of your triangle
}
You can set display:table-cell of main_content and then use vertical-align: middle;
#main_content {
width: 300px;
height: 300px;
background-color: red;
display: table-cell;
vertical-align: middle;
}
I'm having some problems with anchor and image tags. My image tags are sitting inside (what is essentially) a div tag each, the div tags have constant height and width values. The image tags are given a constant height value, so their width can be calculated based on their aspect ratio and the images do not become distorted when they're resized to fit inside the div.
I want to have an anchor tag surrounding each image for two reasons. (1.) So the images can act as links, but also (2.) so that when the user hovers over the image, I can display an overlay on top of the image.
Putting the image tag inside an anchor tag solves the problem of the link, but as for the second problem, I'm stumped. I need the anchor tag to dynamically size and position itself over its respective image tag. Ideally I'd like to avoid using JavaScript to solve the problem and just stick to CSS (if possible). I have no objection to adding a little extra markup if needs be.
Relevant HTML:
<listitem>
<img src="../images/image1.jpg"/>
</listitem>
<!--More listitems with different sized images go here-->
And the CSS:
#pictureListContainer listitem {
position: relative;
background-color: rgba(0,0,0,0.5);
display: block;
height: 257px;
width: 636px;
}
#pictureListContainer listitem img {
position: relative;
float: right;
height: 203px !important;
vertical-align: middle;
margin: 21px 296px 21px auto;
border: 6px solid white;
border-radius: 6px;
box-shadow: 0px 0px 3px rgba(0,0,0,0.7);
}
Thanks in advance.
Update: I should maybe make it clear that I would like the overlay to have the same dimensions as the image, so that it only overlays the image.
It can be done using only CSS and HTML: JSFiddle
HTML
<div class="listitem">
<a href="#">
<img src="http://sublantic.net/forge/demos/img/code_canyon/scale.png" alt="image" />
<span class="overlay-text">Test</span>
</a>
</div>
CSS
.listitem {
position: relative;
background-color: rgba(0,0,0,0.5);
display: block;
height: 257px;
width: 636px;
overflow: hidden;
}
.listitem img {
position: relative;
float: right;
height: 203px !important;
vertical-align: middle;
margin: 21px 296px 21px auto;
border: 6px solid white;
border-radius: 6px;
box-shadow: 0px 0px 3px rgba(0,0,0,0.7);
position: relative;
}
.listitem a span {
display: none;
position: absolute;
bottom: 10px;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
width: 100%;
padding: 10px;
color: #FFF;
}
.listitem a:hover span {
display: block;
}
Edit: Overlay fits to image
JSFiddle
CSS
.listitem {
position: relative;
background-color: rgba(0,0,0,0.5);
display: block;
height: 257px;
width: 636px;
}
.listitem img {
border: 6px solid white;
border-radius: 6px;
box-shadow: 0px 0px 3px rgba(0,0,0,0.7);
}
.listitem a {
position: relative;
overflow: hidden;
display: inline-block;
}
.listitem a span {
display: none;
position: absolute;
bottom: 10px;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
width: 100%;
padding: 10px;
color: #FFF;
}
.listitem a:hover span {
display: block;
}
You can use an onClick for the image
<img src="" onClick="" />
This will eliminate the botheration of generating functionality like overlay, etc for a tag and you can get both effects work simultaneously well.
Hope this helps.