Create an even shadow on a full-width element - html

When a box-shadow is applied to an element the corners are less "thick" than the middle because they don't have shadow on both sides. This creates an odd effect on full width elements.
http://jsfiddle.net/kevincox/6FhYe/18/
If you look at that example you will see that the edges are lighter. If the "banner" is at the top of a page you can spread it and shift it up but that doesn't work for the middle of the page as you can see the top.
I was wondering if anyone had a solution with no images and preferably cross-browser but I can deal with vendor prefixes for a bit. Is there something like a separate horizontal and vertical stretch?

One trick that seems to work is setting negative horizontal margins on the element, so that its ends extend outside the page, and adjusting the padding to compensate. Using your jsFiddle as an example, try changing the CSS to:
h1 {
margin: 20px -20px;
padding: 10px 30px;
background-color: #AFA;
box-shadow: 0 0 10px black;
}

Take a look at this updated jsfiddle
Each number in the shadows represents the following
The horizontal offset of the shadow, positive means the shadow will
be on the right of the box, a negative offset will put the shadow on
the left of the box.
The vertical offset of the shadow, a negative one means the
box-shadow will be above the box, a positive one means the shadow
will be below the box.
The blur radius (optional), if set to 0 the shadow will be sharp,
the higher the number, the more blurred it will be.
The spread radius (optional), positive values increase the size of
the shadow, negative values decrease the size. Default is 0 (the
shadow is same size as blur).
Color

Applying border-radius also fixes this issue (but obviously it depends on whether you want that in your design).
h1 {
margin: 10px;
padding: 10px;
border-radius: 10px;
background-color: #AFA;
box-shadow: 1px 0 10px black;
}

Related

Border included in the layout/ frame of an element, instead of being around it? (Like stroke: included on Figma)

Hope you're all doing fine. I have a question regarding borders in CSS.
I have a button that is 48px height, but padding sets its size dynamically instead of hardcoding the 48px height value. When I give it a 2px border, the button ends up being 52px because of the extra 2px on top and bottom.
Is there a way to include border in the total height? Like border included in layout? There is a specific reason that I don't wanna lower padding with 4px in total. Maybe stack the border on top of the padding? Is this possible?
Further reading: https://forum.figma.com/t/borders-are-not-included-in-the-size-of-frames/2372

CSS: Make image padding not affect shadow

So, i have simple css but big problem...
.separator a img {
width: 100%;
height: auto;
padding: 12px;
}
And the result is: this
As you can see on the image, shadow is showing on padding of the image but i want it to show on the image.
I want to do this but also to keep the padding.
Any ideas?
You're looking for the margin CSS property. Padding goes on the inside of the border-box, whereas margin goes outside.
Since the shadow is (I'm assuming) applied via box-shadow, the margin will be outside of it and the shadow will display directly adjacent to the image.
Try changing padding: 12px to margin: 12px.
Try using margin instead of padding. Think of padding as being 'inside' the box, and margin as being the space between the box and other things on the page.

Is it possible to position an element relative to the border-box of its parent?

Consider the following jsfiddle for reference:
http://jsfiddle.net/apmmw2ma/
<div class='outer'>
<div class='inner'>
Inner.
</div>
Outer.
</div>
div.outer {
position: absolute;
left: 10px;
top: 10px;
border: 5px solid green;
padding: 10px;
}
div.inner {
position: absolute;
left: 0;
top: 100%;
border: 10px solid red;
padding: 15px;
}
As you can see, the “inner” box (with the red border) is positioned relative to the outer’s padding-box: left:0 positions it just to the right of outer’s border, and top:100% appears to mean “100% of the content plus padding, but not the border”.
Unfortunately, adding box-sizing: border-box to the outer div seems to have no effect.
I want to position a child element directly below its parent’s border-box, i.e. the two borders should abut no matter how thick they are. Is this possible?
Unfortunately this is not possible without knowing the border widths in advance. If you don't know the border widths in advance, or if they are dynamic, then you're out of luck.1
The area of an element's containing block is indeed defined as the padding edge of the element forming the containing block. This is explicitly stated in the spec, and is by design; descendants aren't normally supposed to overflow the border of their container, unless the container has overflow: visible and does not establish a BFC (and even then, the effect is only visual; it doesn't affect layout). Otherwise, the border isn't much of a border anymore.
Generally, if you want to lay out elements such that they interact by their border or outer edges, you don't want to lay them out as ancestors and descendants. At the very least you want them to be siblings2, otherwise they should be completely unrelated.
This seems like an oversight to me; the meaning of top: x% should really depend on the box-sizing value of the parent...
The purpose of box-sizing is to change how the size of a box is calculated (i.e. whether or not the padding or the borders should add to the dimensions specified by width and height); while you can use it to alter the size of an element's padding box, the area of the containing block, if the element generates one, is still defined by that padding box.
1 This could conceivably be solved with custom properties, but on the precondition that you must assign the same custom property to both the parent's border-width and to the child's respective offsets, which is basically another way of saying "you must know the border widths in advance" or at least, have control over them.
2 Floats, for example, are highly predisposed to the border edge of boxes, so much so that they can appear to collapse margins in places where you normally wouldn't expect it to occur.
Unfortunately it is not possible to do this without repeating the value of the parent’s border width.
However, if repeating the border width value is acceptable, the following solution works:
div.inner {
top: <desired top value, e.g. 100%>;
margin-top: <parent’s border-bottom-width>;
left: <desired left value, e.g. 0>;
margin-left: -<parent’s border-left-width>;
}
In the future, the same will be possible with calc(), which at the time of this writing is not widely enough supported:
div.inner {
top: calc(<desired top value, e.g. 100%> + <parent’s border-bottom-width>);
left: calc(<desired left value, e.g. 0> - <parent’s border-left-width>);
}
If I may dream for the future, I would like to be able to refer to the property values of the parents/ancestors inside a calc() expression. Then I could write something like:
/* Hypothetical code that will never work */
div.inner {
top: calc(100% + parent.border-bottom-width);
left: calc(0 - parent.border-left-width);
}
Use box-shadow
This makes use of the box-sizing model the way you expect:
http://jsfiddle.net/apmmw2ma/6/
-webkit-box-shadow:inset 0px 0px 0px 5px green;
-moz-box-shadow:inset 0px 0px 0px 5px green;
box-shadow:inset 0px 0px 0px 5px green;
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
Try using display:table; for the outer div.
Fiddle: http://jsfiddle.net/apmmw2ma/9/

Zoom-out bug in chrome, IE, etc, with borders?

Simple test case:
http://cssdesk.com/K2xmN
Another Example:
http://developer.nokia.com/
Problem: When you change the zoom page to 90%, the border goes to 1.111 (1.333 at 75%) and breaks the layouts.
In the nokia website, you can see the top containers break because there is no space left. In the CSSDesk testcase, if you inspect the computed styles, you can see the border width going higher.
Why this happen? border is not set in EM or %, why does it scale?
The why has been explained but I though I'd share a workaround which I just discovered:
Often you can replace the border with a box-shadow that looks just like a border but doesn't add to the outer width of the element:
Instead of
border: 1px solid red;
write
box-shadow: inset 0 0 0 1px red;
width: 102px;
height: 102px;
The width and height of the div have to be adjusted accordingly to accomodate to the fact that the 1px of the borders on each side are gone now.
Now when zooming out the browser will still treat the box-shadow the same as the border, i.e. it won't shrink below 1px, but it will not influence the width of the element and thus the layout won't break.
Alternatively, you can probably use box-sizing: border-box; to some similar effect.
This is an artifact of the problem of scaling down a 1px border. To illustrate what happens, I have modified your test case to include zoom: 0.5;
in the css: http://cssdesk.com/zn4Lx
Notice that if you inspect the computed style, the border width will be 2px. What happens is that Chrome tries to scale down the element, but after scaling, the border still has to be 1px wide if it is to remain visible (after all, 1px is the smallest unit that can be rendered on the computer screen, and if the border width is scaled down to a floating point number smaller than 1.0, it will be rounded down to 0px and disappear). But to justify the scaling, it over-compensates by adjusting the initial width to satisfy the equation
new_width = old_width * scale
In this example, since new_width = 1px, and scale = 0.5, it re-calculates old_width as 2px. Note however that the actual width of the border that is rendered after the scaling is still just 1px.
So in your example, the adjusted old width will be approximately 1.11111111px, and the rendered border width will be 1px wide, but since all the other widths in the layout that are larger than 1px also have been scaled down by approximately 90%, there is no room for a 1px wide border, which results in a broken layout.
The box shadow solution by Shepard might not work well for elements with children that occupy all their space because the shadow will be covered by the children.
Another fix would be to use a border width larger than 1px but smaller than 1.5px.
border-width: 1.3px;
I found 1.3px or 1.4px to be the ideal value and it works in Chrome and IE11 with zoom >= 75%

Background image - padding changes size of background (with display block)

When you change the padding(top, bottom), it also changes (add 10px) the height of the background. How can I fix this? Vertically, it seems to work well.
http://jsfiddle.net/VyYB7/3/
I have added padding to my text/content.
Try using margin instead (or in addition) of padding, like so:
margin: 10px 0;
EDIT
To use both padding and margin (so that the text will be padded):
margin: 10px 10px;
padding: 0 10px;
Check out the CSS background-origin and background-clip properties. Set them to whatever works to get your background anchored in the right place (probably content-box for both).