If an element exists on a page with more than one border color, the corner where these colors meet create a bevel by default. This seems like an odd choice for the border-corner style. I would instead prefer that one of the borders "overpowers" the other border such that a straight line is shown instead.
To illustrate this effect, consider the following:
See example jsFiddle example I created here.
The top two items display the default, beveled behavior. The bottom two display the desired, expected behavior, where in this case, border-top "overpowers" or "overrides" the corner of border-left and border-right.
The markup for the top case:
<div class="container">
<div class="border">Item one</div>
<div class="border">Item two</div>
</div>
And the CSS:
.container {
margin: 5px;
width: 150px;
background: yellow;
}
.border {
padding: 5px;
border: 15px solid red;
border-top: 15px solid teal;
}
The markup for the bottom case:
<div class="container">
<div class="border-top"></div>
<div class="border-reg">Item one</div>
<div class="border-top"></div>
<div class="border-reg">Item two</div>
</div>
And the CSS:
.border-top {
border-top: 15px solid teal;
}
.border-reg {
border: 15px solid red;
border-top: 0;
padding: 5px;
}
Although the second method I devised does produce the effect I want, it seems as if this is unnecessarily tedious for something that I would have assumed to have the default state. If I were to want the border-left to override the other borders, for example, I would have to deal with some float: left and inline element madness.
The Question (Finally)
Is there any easier method of removing the default bevel-behavior observed on all browsers?
Although the case detailed above is mostly easy for having the border-top or border-bottom overriding the corners, it is not as easy of a task, for example, if I need the border-left and border-right to override the border-top and border-bottom.
If you don't need support for older browsers (IE 8 and less) you can use box-shadow:
.border {
padding : 35px 20px 20px 20px;
box-shadow: inset 0 0 0 15px red, inset 0 15px 0 15px teal;
}
http://jsfiddle.net/fTGDs/
That's the way borders work, I believe there's no way to change this without an extra element.
Instead of empty divs, you can use wrapper divs.
<div class="outer">
<div class="inner">test</div>
</div>
.inner {
padding : 5px;
border : 15px solid red;
border-top: 0;
}
.outer {
border-top : 15px solid teal;
}
Demo: http://jsfiddle.net/fmcvY/
There's another way to do it with :before/:after psuedo elements but it's a little messier, however it requires no extra markup:
<div>test</div>
div {
padding : 5px;
border : 15px solid red;
border-top: 0;
position:relative;
padding-top: 20px; /* border width plus desired padding */
}
div:before {
content:' ';
display:block;
background: teal;
height:15px;
padding:0 15px; /* border width plus div padding */
width:100%;
position:absolute;
top: 0;
left:-15px; /* border width plus div padding */
}
You can write the CSS in a number of different ways to achieve the same effect. Demo: http://jsfiddle.net/fmcvY/3/
Related
EDIT: Chromium-specific issue it seems...
I'm using a div element that contains other div elements, like a column with cells in a table. Columns are next to each other with proper absolute positioning. When I use box-shadow inset to emulate borders, things look great, until the outermost container gets a transform scale on it, then the box-shadow border leaks into vertical borders when I only want horizontal borders. Any ideas?
CodePen:
https://codepen.io/mattalie/pen/RwazNmj
<div class='container'>
<div class='group'>
<div class='col' style='left:5px;width:125px'>
<div class='cell'>2000</div>
<div class='cell'>2000</div>
<div class='cell'>2000</div>
</div>
<div class='col' style='left:130px;width:125px'>
<div class='cell'>asdfasdf</div>
<div class='cell'>asdfasdf</div>
<div class='cell'>asdfasdf</div>
</div>
<div class='col' style='left:255px;width:125px'>
<div class='cell'>999999</div>
<div class='cell'>999999</div>
<div class='cell'>999999</div>
</div>
</div>
</div>
.container {
transform: scale(0.672);
}
.group {
font-size: 28px;
position: absolute;
left: 0;
top: 0;
width: 500px;
height: 200px;
background-color: red;
}
.col {
position: absolute;
overflow: hidden;
background-color: yellow;
}
.cell {
position: relative;
padding: 5px 8px 5px 8px;
color: #000000;
background-color: #ffffff;
box-shadow: inset 0px -3px 0px #000000;
box-sizing: border-box;
}
Thanks in advance, this one is killing me.
Pic - vertical lines should not be there
It doesn't seem to have to do with box-shadow. Chrome seems to have problems with rounding when using transform and which creates gaps between elements so that the background shines through.
Here are two other posts that have similar problems:
Transform Scale Causing Gaps/Lines
Scaling results in gaps between CSS shapes
However there doesn't seem to be a universal solution. Based on those posts and some experiments my first suggestion would be to take a step back and to look for a different solution to your design.
What you are currently doing seems to be a bit hacky to me (absolute positioning, using box-shadow to emulate borders) anyway, so you may want to re-consider these choices and also check if you need to use transform or if you need to have different background colors and and a box-shadow here which shine through the gaps.
Alternatively one even more hacky solution would ironically use normal (outer) box-shadows to fill in the gaps, in your case a white shadow on the columns and cells:
.col {
/* ... */
box-shadow: 0 0 0 1px white;
}
.cell {
/* ... */
box-shadow: inset 0px -3px 0px #000000, 0 0 0 1px white;
}
To make it easier, I created a jsFiddle for this here: http://jsfiddle.net/ond1ju6p/
I am trying to get three divs to align besides each other on top of another div. I thought that giving the first two the width of 33.33% and the third one a width of 33.34%, it would equal the 100% width but that's not working.
What am I doing wrong?
Here is the HTML
<div class="box-top">
<div class="box-top-left">Pig One</div>
<div class="box-top-center">Pig Two</div>
<div class="box-top-right">Pig Three</div>
</div>
<div class="box-bottom">Three little piggies had an awesome day.</div>
And the CSS
.box-top-left {
background-color: #FFF;
padding: 0px;
border-width: 1px 1px 1px 0px;
border: 1px solid #C4C4C4;
border-radius: 5px 5px 0px 0px;
display: inline-block;
width: 33.33%;
}
.box-top-center {
background-color: #CCC;
padding: 0px;
border-width: 1px 1px 1px 0px;
border: 1px solid #C4C4C4;
border-radius: 5px 5px 0px 0px;
display: inline-block;
width: 33.33%;
}
.box-top-right {
background-color: #CCC;
padding: 0px;
border-width: 1px 1px 1px 0px;
border: 1px solid #C4C4C4;
border-radius: 5px 5px 0px 0px;
display: inline-block;
width: 33.34%;
}
.box-bottom {
background-color: #FFF;
padding: 10px 30px;
border-width:0px 1px 1px 1px;
border-radius: 0px 0px 5px 5px;
border: 1px solid #C4C4C4;
}
The issue is because Inline-block divs respect whitespace. Thus your divs have tiny gaps between them from the return key.
Change:
<div class="box-top">
<div class="box-top-left">Pig One</div>
<div class="box-top-center">Pig Two</div>
<div class="box-top-right">Pig Three</div>
</div>
to this:
<div class="box-top">
<div class="box-top-left">Pig One</div><div class="box-top-center">Pig Two</div><div class="box-top-right">Pig Three</div>
</div>
and then add the following css rule to your divs:
box-sizing: border-box;
and it works for me.
Border-box makes the border included in the width size. It has good cross browser support.
js fiddle: http://jsfiddle.net/ond1ju6p/2/
edit: you could also try adding display:flex to the parent instead of removing whitespace.
.box-top {
display:flex;
}
.box-top > div {
box-sizing: border-box;
}
Flex solution fiddle: http://jsfiddle.net/ond1ju6p/3/
You can use display table and table-cell like so:
.box-top {
display: table;
width: 100%;
}
.box-top-left,
.box-top-center,
.box-top-right {
display: table-cell;
width: 33%;
}
The problem is, that you add 1px of border to each side, and thus the boxes become larger than 33.33%. (The border is added by your browser after it has already set the width). The easiest way to fix it would be using calc(33.33% - 2px) as the width.
There are two issues hanging this up.
First is that inline blocks have implicit spacing, so they don't automatically bump right up against one another. That extra spacing is variable by browser and font size, so to get rid of it you can set font-size: 0 on the container element (in this case, .box-top). Of course you then need to reset the font-size on your child elements.
The next issue is that width doesn't include padding or border by default. So your boxes are 33.33%, plus another 2px (the border on both sides). The easiest fix for that is box-sizing: border-box on each child box, which will then include the border inside the width calculation. That would work on most newer browsers, but if your target browser doesn't support box-sizing (most do now, but check http://caniuse.com/#feat=css3-boxsizing) then you would need to fix it so that your boxes are even narrower to make sure the 1px border fits, and that can become a mess.
I would add "float:left;" and "box-sizing:border-box;" (without quotes) to .box-top-left, -middle, and -right and then "clear:both;" to .box-bottom. If that doesn't work I would also make all the widths for those 3 boxes 33.33%.
I have a menu, when the menu item is active it should have a border to the right, the issue is that the border is doesn't render correctly, please notice the bottom edge of the border.
This image shows the issue:
http://imgur.com/FC1n8qA
Jsfiddle: http://jsfiddle.net/2yj3hyqm/5/ (See full screen for better view)
CSS code:
.border {
border-right:4px solid #000;
}
Thanks,
The rendering is correct.
Take a look at this:
border: 10px solid black;
border-right-color: red;
border-bottom-color: blue;
border-left-color: green;
Note how the borders meet at the corners. Your menu items have a thick right border and a thin bottom border. The way borders meet at the corners the thick right border looks slightly crooked at the bottom. Try and remove the bottom border and see how the right border gets straight again.
You can try nesting elements in the menu item and apply the border-bottom and border-right to different elements or use a pseudo element to fix the appearance.
As mentioned, the problem is the bottom border overlaping the right one. So, a possible solution is to "fake" a border using :after pseudo, placing it at the right of the element:
Updated JSFIDDLE
.border {
position: relative;
}
.border:after {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: 4px;
background: black;
content: "\00a0"; /* invisible content */
}
Borders meet at angles so you would have to use an alternative for the right border
A box-shadow would work quite well
JSfiddle Comparison (exaggerated)
HTML
<div class="border"> </div>
<div class="shadow"> </div>
CSS
.border,
.shadow {
background-color: grey;
width:100px;
height:100px;
margin-bottom: 10px;
border-bottom: 5px solid lightgrey;
}
.border{
border-right: 20px solid black;
}
.shadow {
box-shadow: 10px 0 0px 0 black;
}
If an element exists on a page with more than one border color, the corner where these colors meet create a bevel by default. This seems like an odd choice for the border-corner style. I would instead prefer that one of the borders "overpowers" the other border such that a straight line is shown instead.
To illustrate this effect, consider the following:
See example jsFiddle example I created here.
The top two items display the default, beveled behavior. The bottom two display the desired, expected behavior, where in this case, border-top "overpowers" or "overrides" the corner of border-left and border-right.
The markup for the top case:
<div class="container">
<div class="border">Item one</div>
<div class="border">Item two</div>
</div>
And the CSS:
.container {
margin: 5px;
width: 150px;
background: yellow;
}
.border {
padding: 5px;
border: 15px solid red;
border-top: 15px solid teal;
}
The markup for the bottom case:
<div class="container">
<div class="border-top"></div>
<div class="border-reg">Item one</div>
<div class="border-top"></div>
<div class="border-reg">Item two</div>
</div>
And the CSS:
.border-top {
border-top: 15px solid teal;
}
.border-reg {
border: 15px solid red;
border-top: 0;
padding: 5px;
}
Although the second method I devised does produce the effect I want, it seems as if this is unnecessarily tedious for something that I would have assumed to have the default state. If I were to want the border-left to override the other borders, for example, I would have to deal with some float: left and inline element madness.
The Question (Finally)
Is there any easier method of removing the default bevel-behavior observed on all browsers?
Although the case detailed above is mostly easy for having the border-top or border-bottom overriding the corners, it is not as easy of a task, for example, if I need the border-left and border-right to override the border-top and border-bottom.
If you don't need support for older browsers (IE 8 and less) you can use box-shadow:
.border {
padding : 35px 20px 20px 20px;
box-shadow: inset 0 0 0 15px red, inset 0 15px 0 15px teal;
}
http://jsfiddle.net/fTGDs/
That's the way borders work, I believe there's no way to change this without an extra element.
Instead of empty divs, you can use wrapper divs.
<div class="outer">
<div class="inner">test</div>
</div>
.inner {
padding : 5px;
border : 15px solid red;
border-top: 0;
}
.outer {
border-top : 15px solid teal;
}
Demo: http://jsfiddle.net/fmcvY/
There's another way to do it with :before/:after psuedo elements but it's a little messier, however it requires no extra markup:
<div>test</div>
div {
padding : 5px;
border : 15px solid red;
border-top: 0;
position:relative;
padding-top: 20px; /* border width plus desired padding */
}
div:before {
content:' ';
display:block;
background: teal;
height:15px;
padding:0 15px; /* border width plus div padding */
width:100%;
position:absolute;
top: 0;
left:-15px; /* border width plus div padding */
}
You can write the CSS in a number of different ways to achieve the same effect. Demo: http://jsfiddle.net/fmcvY/3/
I have a <div> element and I want to put a border on it. I know I can write style="border: 1px solid black", but this adds 2px to either side of the div, which is not what I want.
I would rather have this border be -1px from the edge of the div. The div itself is 100px x 100px, and if I add a border, then I have to do some mathematics to make the border appear.
Is there any way that I can make the border appear, and ensure the box will still be 100px (including the border)?
Set box-sizing property to border-box:
div {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
width: 100px;
height: 100px;
border: 20px solid #f00;
background: #00f;
margin: 10px;
}
div + div {
border: 10px solid red;
}
<div>Hello!</div>
<div>Hello!</div>
It works on IE8 & above.
You can also use box-shadow like this:
div{
-webkit-box-shadow:inset 0px 0px 0px 10px #f00;
-moz-box-shadow:inset 0px 0px 0px 10px #f00;
box-shadow:inset 0px 0px 0px 10px #f00;
}
Example here: http://jsfiddle.net/nVyXS/ (hover to view border)
This works in modern browsers only. For example: No IE 8 support.
See caniuse.com (box-shadow feature) for more info.
Probably it is belated answer, but I want to share with my findings. I found 2 new approaches to this problem that I have not found here in the answers:
Inner border through box-shadow css property
Yes, box-shadow is used to add box-shadows to the elements. But you can specify inset shadow, that would look like a inner border rather like a shadow. You just need to set horizontal and vertical shadows to 0px, and the "spread" property of the box-shadow to the width of the border you want to have. So for the 'inner' border of 10px you would write the following:
div{
width:100px;
height:100px;
background-color:yellow;
box-shadow:0px 0px 0px 10px black inset;
margin-bottom:20px;
}
Here is jsFiddle example that illustrates the difference between box-shadow border and 'normal' border. This way your border and the box width are of total 100px including the border.
More about box-shadow:here
Border through outline css property
Here is another approach, but this way the border would be outside of the box. Here is an example.
As follows from the example, you can use css outline property, to set the border that does not affect the width and height of the element. This way, the border width is not added to the width of an element.
div{
width:100px;
height:100px;
background-color:yellow;
outline:10px solid black;
}
More about outline: here
Yahoo! This is really possible. I found it.
For Bottom Border:
div {box-shadow: 0px -3px 0px red inset; }
For Top Border:
div {box-shadow: 0px 3px 0px red inset; }
You can use the properties outline and outline-offset with a negative value instead of using a regular border, works for me:
div{
height: 100px;
width: 100px;
background-color: grey;
margin-bottom: 10px;
}
div#border{
border: 2px solid red;
}
div#outline{
outline: 2px solid red;
outline-offset: -2px;
}
Using a regular border.
<div id="border"></div>
Using outline and outline-offset.
<div id="outline"></div>
Although this question has already been adequately answered with solutions using the box-shadow and outline properties, I would like to slightly expand on this
for all those who have landed here (like myself) searching for a solution for an inner border with an offset
So let's say you have a black 100px x 100px div and you need to inset it with a white border - which has an inner offset of 5px (say) - this can still be done with the above properties.
box-shadow
The trick here is to know that multiple box-shadows are allowed, where the first shadow is on top and subsequent shadows have lower z-ordering.
With that knowledge, the box-shadow declaration will be:
box-shadow: inset 0 0 0 5px black, inset 0 0 0 10px white;
div {
width: 100px;
height: 100px;
background: black;
box-shadow: inset 0 0 0 5px black, inset 0 0 0 10px white;
}
<div></div>
Basically, what that declaration is saying is: render the last (10px white) shadow first, then render the previous 5px black shadow above it.
outline with outline-offset
For the same effect as above the outline declarations would be:
outline: 5px solid white;
outline-offset: -10px;
div {
width: 100px;
height: 100px;
background: black;
outline: 5px solid white;
outline-offset: -10px;
}
<div></div>
NB: outline-offset isn't supported by IE if that's important to you.
Codepen demo
Use pseudo element:
.button {
background: #333;
color: #fff;
float: left;
padding: 20px;
margin: 20px;
position: relative;
}
.button::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 5px solid #f00;
}
<div class='button'>Hello</div>
Using ::after you are styling the virtual last child of the selected element. content property creates an anonymous replaced element.
We are containing the pseudo element using absolute position relative to the parent. Then you have freedom to have whatever custom background and/or border in the background of your main element.
This approach does not affect placement of the contents of the main element, which is different from using box-sizing: border-box;.
Consider this example:
.parent {
width: 200px;
}
.button {
background: #333;
color: #fff;
padding: 20px;
border: 5px solid #f00;
border-left-width: 20px;
box-sizing: border-box;
}
<div class='parent'>
<div class='button'>Hello</div>
</div>
Here .button width is constrained using the parent element. Setting the border-left-width adjusts the content-box size and thus the position of the text.
.parent {
width: 200px;
}
.button {
background: #333;
color: #fff;
padding: 20px;
position: relative;
}
.button::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 5px solid #f00;
border-left-width: 20px;
}
<div class='parent'>
<div class='button'>Hello</div>
</div>
Using the pseudo-element approach does not affect the content-box size.
Depending on the application, approach using a pseudo-element might or might not be a desirable behaviour.
I know this is somewhat older, but since the keywords "border inside" landed me directly here, I would like to share some findings that may be worth mentioning here.
When I was adding a border on the hover state, i got the effects that OP is talking about. The border ads pixels to the dimension of the box which made it jumpy.
There is two more ways one can deal with this that also work for IE7.
1)
Have a border already attached to the element and simply change the color. This way the mathematics are already included.
div {
width:100px;
height:100px;
background-color: #aaa;
border: 2px solid #aaa; /* notice the solid */
}
div:hover {
border: 2px dashed #666;
}
2 )
Compensate your border with a negative margin. This will still add the extra pixels, but the positioning of the element will not be jumpy on
div {
width:100px;
height:100px;
background-color: #aaa;
}
div:hover {
margin: -2px;
border: 2px dashed #333;
}
11 Years Later but heres the answer:
Just use outline:
outline: 0.2vw solid red;
I hope i can help someone who sees this question also 11 Yeas Later.
for consistent rendering between new and older browsers, add a double container, the outer with the width, the inner with the border.
<div style="width:100px;">
<div style="border:2px solid #000;">
contents here
</div>
</div>
this is obviously only if your precise width is more important than having extra markup!
If you use box-sizing: border-box means not only border,
padding,margin, etc. All element will come inside of the parent
element.
div p {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
width: 150px;
height:100%;
border: 20px solid #f00;
background-color: #00f;
color:#fff;
padding: 10px;
}
<div>
<p>It was popularised in the 1960s with the release of Letraset sheets</p>
</div>
Best cross browser solution (mostly for IE support) like #Steve said is to make a div 98px in width and height than add a border 1px around it, or you could make a background image for div 100x100 px and draw a border on it.
You can look at outline with offset but this needs some padding to exists on your div. Or you can absolutely position a border div inside, something like
<div id='parentDiv' style='position:relative'>
<div id='parentDivsContent'></div>
<div id='fakeBordersDiv'
style='position: absolute;width: 100%;
height: 100%;
z-index: 2;
border: 2px solid;
border-radius: 2px;'/>
</div>
You might need to fiddle with margins on the fake borders div to fit it as you like.
A more modern solution might be to use css variables and calc. calc is widely supported but variables is not yet in IE11 (polyfills available).
:root {
box-width: 100px;
border-width: 1px;
}
#box {
width: calc(var(--box-width) - var(--border-width));
}
Although this does use some calculations, which the original questions was looking to avoid. I think this is an ok time to use calculations as they are controlled by the css itself. It also has no need for additional markup or misappropriating other css properties that may be needed later on.
This solution is only really useful if a fixed height isn't needed.
One solution I didn't see mentioned above is the case where you have padding on your input, which I do 99% of the time. You can do something along the lines of...
input {
padding: 8px;
}
input.invalid {
border: 2px solid red;
padding: 6px; // 8px - border or "calc(8px - 2px)"
}
What I like about this is that I have the full menu of border + padding + transition properties for each side.