What is the difference between outline and border CSS properties? - css

What is the difference between border and outline properties in CSS?
If there is no difference, then why are there two properties for the same thing?

From: http://webdesign.about.com/od/advancedcss/a/outline_style.htm
The CSS outline property is a confusing property. When you first learn about it, it's hard to understand how it is even remotely different from the border property. The W3C explains it as having the following differences:
Outlines do not take up space.
Outlines may be non-rectangular.

In addition to some other answers... here are a few more differences I can think of:
1) Rounded corners
border supports rounded corners with the border-radius property. outline doesn't.
div {
width: 150px;
height: 150px;
margin: 20px;
display: inline-block;
position: relative;
}
.border {
border-radius: 75px;
border: 2px solid green;
}
.outline {
outline: 2px solid red;
border-radius: 75px;
-moz-outline-radius: 75px;
outline-radius: 75px;
}
.border:after {
content: "border supports rounded corners";
position: absolute;
bottom: 0;
transform: translateY(100%);
}
.outline:after {
content: "outline doesn't support rounded corners";
position: absolute;
bottom: 0;
transform: translateY(100%);
}
<div class="border"></div>
<div class="outline"></div>
FIDDLE
(NB: Although firefox has the -moz-outline-radius property which allows rounded corners on outline... this property it is not defined in any CSS standard, and is not supported by other browsers (source))
2) Styling one side only
border has properties to style each side with border-top:, border-left: etc.
outline can't do this. There's no outline-top: etc. It's all or nothing. (see this SO post)
3) offset
outline supports offset with the property outline-offset. border doesn't.
.outline {
margin: 100px;
width: 150px;
height: 150px;
outline-offset: 20px;
outline: 2px solid red;
border: 2px solid green;
background: pink;
}
<div class="outline"></div>
FIDDLE
Note: All major browsers support outline-offset except Internet Explorer

Further to other answers, outlines are usually used for debugging. Opera has some nice user CSS styles that use the outline property to show you where all the elements are in a document.
If you're trying to find out why an element isn't appearing where you expected or at the size you expected, add a few outlines and see where the elements are.
As already mentioned, outlines do not take up space. When you add a border, the element's total width/height in the document increases, but that doesn't happen with outline. Also you can't set outlines on specific sides like borders; it's all or nothing.

tldr;
The W3C explains it as having the following differences:
Outlines do not take up space.
Outlines may be non-rectangular.
Source
Outline should be used for accessibility
It should also be noted that outline's primary purpose is accessibility. Setting it to outline: none should be avoided.
If you must remove it it maybe a better idea to provide alternative styling:
I’ve seen quite a few tips on how to remove the focus indicator by using outline:none or outline:0. Please do not do this, unless you replace the outline with something else that makes it easy to see which element has keyboard focus. Removing the visual indicator of keyboard focus will give people who rely on keyboard navigation a really hard time navigating and using your site.
Source: "Do Not Remove the Outline from Link and Form Controls", 365 Berea Street
More Resources
http://outlinenone.com/

A practical use of outline deals with transparency. If you have a parent element with a background, but want a child element's border to be transparent so that the parent's background will show through, you must use "outline" rather than "border." While a border can be transparent, it will show the child's background, not the parent's.
In other words, this setting created the following effect:
outline: 7px solid rgba(255, 255, 255, 0.2);

From W3 School Site
The CSS border properties allow you to specify the style and color of an element's border.
An outline is a line that is drawn around elements (outside the borders) to make the element "stand out".
The outline shorthand property sets all the outline properties in one declaration.
The properties that can be set, are (in order): outline-color, outline-style, outline-width.
If one of the values above are missing, e.g. "outline:solid #ff0000;", the default value for the missing property will be inserted, if any.
Check here for more information :
http://webdesign.about.com/od/advancedcss/a/outline_style.htm

Border is created inside the element, where as outline is created outside the element. So border is computed along with the width and height of the element, while outline draws outside the element.

A little bit of an old question, but worth mentioning a Firefox rendering bug (still present as of Jan '13) where the outline will render on the outside of all child elements even if they overflow their parent (through negative margins, box-shadows, etc.)
You can fix this with:
.container {
position: relative;
}
.container:before {
content: '';
margin: 0;
padding: 0;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: 1px solid #ff0000;
}
Super unfortunate that it's still not fixed. I much prefer outlines in many cases since they do not add to the dimensions of an element, saving you from always having to consider border widths when setting dimensions of an element.
After all, which is simpler?
.container {
width: 960px;
height: 300px;
outline: 3px solid black;
}
Or:
.container {
width: 954px;
height: 294px;
border: 3px solid black;
}

It is also worth noting, that W3C's outline is IE's border, since IE does not implement W3C box model.
In w3c box model, the border is exclusive of element's width and height. In IE it is inclusive.

Differences between border and outline:
Border is part of the box model so it counts against the element's size.
Outline is not part of the box model so it doesn't affect nearby elements.
Demo:
#border {
border: 10px solid black;
}
#outline {
outline: 10px solid black;
}
<html>
<body>
<span id="border">Border</span>Other text<br><br>
<span id="outline">Outline</span>Other text
</body>
</html>
Other differences:
The outline is displayed outside the border.
Outlines cannot have rounded corners; borders can.

I've made a little piece of css/html code just to see the difference between both.
outline is better to inclose potential overflowing child elements, especially into an inline container.
border is much more adapted for block-behaving elements.
Fiddle for you sir!

The outline property in CSS draws a line around the outside of an element. It's similar to border except that:
It always goes around all the sides, you can't specify particular
sides It's not a part of the box model, so it won't effect the
position of the element or adjacent elements
Source: https://css-tricks.com/almanac/properties/o/outline/

As a practical example of using "outline", the faint dotted border that follows the system focus on a webpage (eg. if you tab through the the links) can be controlled using the outline property (at least, I know it can in Firefox, not tried other browsers).
A common "image replacement" technique is to use, for example:
<div id="logo">Foo Widgets Ltd.</div>
with the following in the CSS:
#logo
{
background: url(/images/logo.png) center center no-repeat;
}
#logo a
{
display: block;
text-indent: -1000em;
}
The problem being that when the focus reaches the tag, the outline heads off 1000em to the left. Outline can allow you to turn off the focus outline on such elements.
I believe that the IE Developer Toolbar is also using something like outline "under the hood" when highlighting elements for inspection in "select" mode. That shows well the fact that "outline" takes up no space.

think about outline as a border that a projector draw outside something as a border is an actual object around that thing.
a projection can easily overlap but border don't let you pass.
some times when i use grid+%width, border will change the scaling on view port,for example a div with width:100% in a parent with width:100px fills the parent completely, but when i add border:solid 5px to div it make the div smaller to make space for border(although it's rare and work-aroundable!) but with outline it doesn't have this problem as outline is more virtual :D it's just a line outside the element
but the problem is if you don't do spacing properly it would overlap with other contents.
to make it short:
outline pros:
it doesn't mess with spacing and positions
cons:
high chance of overlapping

Google web.dev has a good explaintion for Box Model.
The border box surrounds the padding box and its space is occupied by the border value. The border box is the bounds of your box and the border edge is the limit of what you can visually see. The border property is used to visually frame an element.
The margin box, is the space around your box, defined by the margin rule on your box. Properties such as outline and box-shadow occupy this space too because they are painted on top, so they don't affect the size of our box. You could have an outline-width of 200px on our box and everything inside and including the border box would be exactly the same size.

Copied from W3Schools:
Definition and Usage
An outline is a line that is drawn
around elements (outside the borders)
to make the element "stand out".

Related

Why does display inline-block match height of text?

I have an anchor tag, and I'm using the :before selector to add some text. I have added a hover state around the anchor tag. The :before text is slightly larger than the rest of the text in the anchor tag and I'm adding a display: inline-block property to the before text.
When I hover over the anchor tag, the hover state is wrapped tightly around the all the anchor text, including the :before text (EXAMPLE 1 in codepen). Like so:
https://user-images.githubusercontent.com/20184809/52691191-27364e80-2fb4-11e9-9ffe-8777e645acee.png
How ever if I add the display:inline-block property to the anchor tag the hover state is a rectangle which matches the height of the larger :before text. Like so:
https://user-images.githubusercontent.com/20184809/52691272-7da38d00-2fb4-11e9-900b-c795623de3e2.png
Why is this?
.link-1:hover, .link-2:hover {
outline: 3px solid green;
outline-offset: 2px;
}
.link:before {
content:':before text';
font-size: 35px;
display: inline-block;
}
.link-1 {
display: inline-block;
}
<!-- EXAMPLE 2 -->
anchor text
<br>
<!-- EXAMPLE 1 -->
anchor text
EDIT:
I've noticed this happens on Chrome and not Safari and firefox. It could be a browser thing?
From the specification we can read:
Outlines may be non-rectangular. For example, if the element is broken across several lines, the outline is the minimum outline that encloses all the element's boxes. In contrast to borders, the outline is not open at the line box's end or start, but is always fully connected if possible.
And
The outline may be drawn starting just outside the border edge.
For the second example, when making the element inline-block we will have the below
.link-1:hover, .link-2:hover {
outline: 3px solid green;
outline-offset: 2px;
}
.link:before {
content:':before text';
font-size: 35px;
display: inline-block;
}
.link-1 {
display: inline-block;
border:1px solid;
}
anchor text
It's clear that the outline need to at least surround the border and it will be the same for all the browser.
But for the first example we will have this:
.link-1:hover, .link-2:hover {
outline: 3px solid green;
outline-offset: 2px;
}
.link:before {
content:':before text';
font-size: 35px;
display: inline-block;
}
.link,
.link:before{
border:1px solid;
}
<!-- EXAMPLE 2 -->
anchor text
It seems that Chrome in this case is following the borders to draw the outline and is respecting the Specification by keeping it connected. The result is somehow logical but other browser aren't doing the same. I won't say if Firefox is doing wrong but both result are fine and doesn't violate the specification.
In both cases we have :
The minimum outline that encloses all the element's boxes
Always fully connected if possible
May be drawn starting just outside the border edge
There are two types of HTML elements. Inline and Block elements. Block elements take up the full width available to them(With exception of inline blocks, will come back to these). Inline elements only take up as much space as they need, i.e they try to be as small as possible. So just the space around their outer border. When you add display: inline-block you turn the whole thing into a block which is why it becomes rectangular. The difference with inline-blocks is that they also take up as much space as they need but they are also fully rectangular. Check out this answer too CSS display: inline vs inline-block

Css color bottom pixel on click

I am looking to color the bottom pixel (the bottom width pixel, along all the length of the image) of my image to one particular color when I click on it. I would like not to add anything in the html.
Can that be achieved only in css doing something like :
.image:active{
width: 1.5px;
background-color: my_color;
length: 100%;
}
Yes, you can use :active state selector. Basically, you can either add a border on the bottom or create a pseudo-element for this image's child (because not all browsers support :before and :after on images).
Border solution:
.image:active {
border-bottom: 1px solid red;
}
I think you wanna add an border at the bottom of your image on css like :
.image:active {
border-bottom: 1.5px solid #123;
}

StackLayoutPanel Shows white ends at the rounded corners

I'm using GWT's StackLayoutPanel and trying to round the corners of its headers by applying border-radius attribute in the following CSS rule:
.mm-StackPanelHeader {
padding-left: 7px;
font-weight: bold;
font-size: 1.4em;
width: 200px;
border-radius: 5px 5px 0px 0px;
background: #d3def6;
border: 0.5px solid #bbbbdd;
}
When collapsing the header items, the borders don't cover over each other completely, showing ugly white cornered ends.
How to fix this?
Here's the output's snapshot, for a reference.
Assuming you're going for the old widgets' look n' feel, achieving the exact same result will inevitably involve replacing images and messing with the widgets' layout properties (e.g applying negative margins, altering offsets).
Having said that, I managed to get a quick CSS-based solution that seem to target your needs, and is free of further manipulations. I'm sure a more accurate solution is available, as this attempt is far from perfect, but it should provide you with a good starting point.
Abstract
To simulate the old widgets' looks:
Round up the top corners for the item headers.
Apply a background color to the underling container, to avoid those ugly white corners.
Use top round corners on that container as well, to avoid ugly blue corners on it as a result of the background color applied.
Reset the bottom padding of the header items to re-center their content.
Implementation
Add the following rules to your stylesheet:
.gwt-StackLayoutPanel,
.gwt-StackLayoutPanel .gwt-StackLayoutPanelHeader {
background-color: #D3DEF6;
border-radius: 5px 5px 0 0;
}
.gwt-StackLayoutPanel .gwt-StackLayoutPanelHeader {
padding-bottom: 0;
}
Illustration
Here's an snapshot of the final result, as created by manipulating the CSS properties on the GWT showcase live example:
Well, StackLayoutPanel was a definitely a newer version than StackPanel.
But I used the latter in this case because there was no other way, and it worked like a charm!
Thanks to all!

Should border-radius clip the content?

Shouldn't the content of my container be cut off when the container has border-radius?
Sample HTML and CSS:
.progressbar { height: 5px; width: 100px; border-radius: 5px; }
.buffer { width: 25px; height: 5px; background: #999999; }
<div class="progressbar">
<div class="buffer"></div>
</div>
As you can see I use border-radius on the container (.progressbar), but the content (.buffer) goes 'outside' the container. I'm seeing this on Google Chrome.
Is this the expected behavior?
P.S. This isn't about how to fix it, this is about whether it should work like this.
Is this the expected behavior?
Yes, as crazy as it sounds, it actually is. Here's why:
The default overflow for <div> elements (and most other things) is visible, and the spec says this about overflow: visible:
visible
This value indicates that content is not clipped, i.e., it may be rendered outside the block box.
In turn, §5.3 Corner clipping in the Backgrounds and Borders module says:
A box's backgrounds, but not its border-image, are clipped to the appropriate curve (as determined by ‘background-clip’). Other effects that clip to the border or padding edge (such as ‘overflow’ other than ‘visible’) also must clip to the curve. The content of replaced elements is always trimmed to the content edge curve. Also, the area outside the curve of the border edge does not accept mouse events on behalf of the element.
The sentence that I've emphasized specifically mentions that the overflow value of the box must be something other than visible (that means auto, hidden, scroll and others) in order for the corners to clip its children.
If the box is defined to have visible overflow, which like I said is the default for most visual elements, then the content is not supposed to be clipped at all. And that's why the square corners of .buffer go over the rounded corners of .progressbar.
Consequently, the simplest way to get .buffer to clip within .progressbar's rounded corners is to add an overflow: hidden style to .progressbar, as shown in this updated fiddle.
For anybody wondering what a fix would be. The easiest way would be to edit the css.
In the example given this would be a suitable fix:
.progressbar { height: 5px; width: 100px; border-radius: 5px; overflow: hidden; }
.buffer { width: 25px; height: 5px; background: #999999; }
<div class="progressbar">
<div class="buffer"></div>
</div>
Semantically speaking, it's best to simply add a border-radius inherit property to the inner div, hence the new class addition:
.buffer {
border-radius: inherit;
}
As a consequence, for others situation, you can preserve the use of overflow: auto if the content overflows your frae and you want to see everything.
The edges and corners of the parent container are covered by quilt elements, so the content of the parent element needs to be cropped, as long as the overflow value is set not visible, for example:
.parent {
overflow: hidden;
border-radius: 5px;
}
This question seems to point to the same defect, apparently this is a bug.
CSS3 border-radius clipping issues
Edit
Eek! BoltClock has mentioned that this is indended so I'll post this other SO question on the topic whilst I also hunt for a spec quote on this.
How do I prevent an image from overflowing a rounded corner box with CSS3?
Specification Link
Just for reference, I'll stick the relevant link in - but I can't find anything explicit to the example you've given.
CSS Backgrounds - Rounded Corners
This is what the specifications says, so this is the way it should work. But that doesn't mean that Chrome does it like that.
5.3. Corner Clipping
A box's backgrounds, but not its border-image, are clipped to the appropriate curve (as determined by ‘background-clip’). Other effects that clip to the border or padding edge (such as ‘overflow’ other than ‘visible’) also must clip to the curve. The content of replaced elements is always trimmed to the content edge curve. Also, the area outside the curve of the border edge does not accept mouse events on behalf of the element.
http://www.w3.org/TR/css3-background/#border-radius

IE bug: absolutely-positioned element with a non-transparent background colour

I have an absolutely-positioned DIV that I need to trap onclick events for. It turns out that, in IE7, the DIV seems to have no 'footprint' for things like clicking and even cursor. For example:
div {
width: 200px; height: 200px;
position: absolute;
border: 10px solid black;
cursor: pointer;
}
In IE7, that DIV has no 'footprint': it doesn't react to onclick(), and its cursor doesn't change to the pointer. Curiously, it DOES handle both those over its border - hence the large border in this example. Setting a background-color:
div { background-color: #fff; }
fixes the problem. But, in this case, that's not possible - I need the DIV to have a transparent background.
I've come across this bug in the past, but I cannot for the life of me remember the IE hack to fix it.
Try using a transparent background image.
I would suggest using a 2x2 or bigger .gif that is all transparent pixels. Set it to repeat on x and y and IE shouldn't have an issue with the clicks.
background: transparent url(path/to/spacer.gif) repeat left top;
/* Not all of that is necessary, but I have a tendency to define it anyway. */
Had the same problem and didnt found a better solution than the transparent gif. Note that this problem also occured in IE8 for me. You don't have to use a 2x2 px gif, 1x1 px is enough.

Resources