Why does display inline-block match height of text? - css

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

Related

Expanding the background color rectangle of selected text

According to MDN, outline should work on the ::selection pseudoelement, yet it doesn't seem to when tested on both chrome and ff.
::selection {
background-color:red;
outline:2px dashed blue;
}
My cool text, select me!
I'm creating a text editor and basically it just annoys me how tight fitting the selection background color is. I want to expand it a few pixels and outline would be the right attribute for the job but it doesn't work?
I think the MDN is wrong or not updated, because if we refer to the specification:
The highlight pseudo-elements can only be styled by a limited set of properties that do not affect layout. The following properties apply to the highlight pseudo-elements:
color
background-color
cursor
caret-color
text-decoration and its associated properties
text-shadow
stroke-color, fill-color, and stroke-width
The outline isn't listed which explain why it's not working. Also I don't think you can control the hightlighting area. As explained in the same specification:
For text, the corresponding overlay must cover at least the entire em box and may extend further above/below the em box to the line box edges. Spacing between two characters may also be part of the overlay area, in which case it belongs to the innermost element that contains both characters and is selected when both characters are selected.
We already have the em box which is trivial and your best luck is to have more in case the line box is higher but it will not behave the same cross browser.
Here is a basic example where I use a pseudo element with a big font-size to increase the height of the line-box and I align it in the middle. In this case the selection will cover more than the text but of course this will also affect the layout which is probably not needed and will not work with all the browser.
The below example works on Chrome and doesn't on Fiferfox
p:after {
content: "";
font-size: 30px;
vertical-align: middle;
}
p::selection {
background-color: red;
}
<p>My cool text, select me!</p>
Another important thing is that all the properties applied inside that area cannot overflow it. We know that with text-shadow we can place the shadow far from the text but with the selection it won't be possible because it cannot overflow the hightlighting area:
p {
text-shadow:0 10px 0 red;
}
p::selection {
background-color: red;
text-shadow:0 -10px 0 blue;
}
<p>My cool text, select me!</p>
Notice how the blue text-shadow is partially visible like we have applied overflow:hidden to the red area. So even if you are able to style the selection with outline it's basically impossible to control its dimension which is what you need here.
I think your best option is to rely on JS to create dynamic element or wrap selected text to easily style them. With the CSS, you can only apply some hack that will affect your layout.
Outside the first line, the other line is valid with line-height. As you can see:
div {
line-height:30px;
}
div::selection {
background: yellow;
}
<div>text<br />text<br />text</div>
So, I did a Javascript trick that added the first line for us. I'm also giving font-size: 0px for the first line. So our problem is solved. As you can see:
let a = document.querySelectorAll(".a");
a.forEach(function(par){
par.insertAdjacentHTML('afterbegin','needed text<br />')
})
// for an unseen first line.
.a {
line-height:50px;
}
.a::selection {
background: yellow;
}
.a::first-line {
font-size:0px;
line-height:0px;
}
<div class="a">text</div>

Firefox not respecting overflow: hidden

I am trying to set up a form that displays a vertical separator between two elements that appear side by side. These are the problem parameters:
The height of either element is unknown and will change by virtue of the contents being modified with JavaScript in response to user interaction.
The separator should cover the whole of the elements' shared vertical border, irrespective of which element happens to be taller at any given time.
Given the above it seems that this setup will do the trick:
<div>This is some text on top.</div>
<ol>
<li id="a">Lalalala</li>
<li id="b">Lololol</li>
</ol>
<div>And some text on the bottom.</div>
CSS
ol { overflow: hidden }
li { float: left; width: 5em; padding: 4px }
div { clear: both }
#a { background: gold; min-height: 100px }
#b { background: yellow; border-left: 1px black dotted }
#b { padding-bottom: 400px; margin-bottom: -400px } /* "infinitely" tall */
The idea is that the second element becomes "infinitely tall" by applying bottom padding and gets a left border; elements following the group are brought back into their original position by counteracting the padding with negative bottom margin; and the "unused" portion of the vertical border is hidden by giving the parent overflow: hidden.
This setup indeed works correctly (JsFiddle) on Firefox, Chrome and IE >=8 (my compatibility requirements):
However, when I try to apply the same technique in my real HTML Firefox breaks down and seems to not honor the overflow: hidden set on the parent element. As a result the infinitely tall vertical border bleeds through all elements following the two panels on the page.
Here is a JSFiddle of (simplified) real copy/pasted content together with my actual CSS rules that shows the problem. Note that only Firefox mishandles this; other browsers continue to display it properly.
Correct render:
Firefox render:
I am properly stumped: why would Firefox display the proof of concept correctly and botch the real deal? And how can I fix it?
I was able to fix your JSFiddle by changing the fieldset element to a div or by surrounding the fieldset with a div that had overflow set to hidden. Maybe worth a try. Is the fieldset tag essential to your HTML?

IE7 cutting off border on span tag

I have the following class in my CSS style sheet:
.errormsg {
border:solid 1px Red;
padding:5px 20px 5px 20px;
margin:5px;
color:Red;
font-size:medium;
font-weight:bold;
}
When I view it in IE7, the top and bottom border is cut off the when I use this class on a span tag.
What do I need to add to get it to work in IE7?
I've noticed similar issues with this sort of thing when the Line Height is not large enough. Try increasing it slightly.
<pan> elements are going to be treated as inline elements unless you specify otherwise. Add display: block; to your CSS and go from there. The alternative would be to use a <div> to wrap the error message, since <div>s are treated as block elements by default.
Setting display: inline-block; on the <div> will fix the display issues, and the width will still adapt to the text size:
Demo
You could also spruce it up a little with a css3 text-shadow, box-shadow, and gradient with an icon from iconfinder: Demo

YUI: Aligning the baseline of a YUI button with the text next to it [duplicate]

I'd like to display a YUI button next to some text, but the baseline of the YUI button text does not line up with the baseline of the text next to it. The font family and size is identical for both the button text and the text next to it.
If I use a plain HTML button the text baselines correctly line up.
Here's a live example of the problem.
How can I get the text baselines to line up?
Enclose the adjacent text in a span tag with the following styles:
<span style="vertical-align: middle; display: inline-block; margin-top: -1.1em;">
YUI Button:
</span>
Since the .yui-button has the property display: inline-block, it will behave like a block but stay inline.
By behaving inline, the box model of this element will be attached to the line while the contents of the button will behave like a block. Thus, you'll have to do some sort of vertical adjustment as Phase suggested.
Since the button has a min-height: 2em, you'll have to do some manual adjustment. This:
.yui-skin-sam .yui-button {
margin-bottom: -0.5em; /* adjust for 2em min-height */
vertical-align: baseline; /* use consistent baseline */
}
gave me good results in IE7, FF3, and Chrome, but there is still slight inconsistency among them. You may have explore what other properties are applied at the first span, the first child span, and button that are causing the slight inconsistencies. Of course, you could also adjust the selector to apply to only one instance of the button rather than all yui buttons.
You could also set the min-height to inherit, but then you'll see how the other properties come into play (e.g. the first child (the span in the span before the button) has a block layout).
Alternatively, you could start adding multiple wrappers around the rest of the text so they behave just like the button by building the appropriate spans within spans, but you seem to want to avoid that. If you do, check a couple different browsers.
On line 7 in button.css there is
.yui-button {
display:-moz-inline-box;
vertical-align:text-bottom;
}
If you remove the vertical-align statement the adjacent text will line up with the button text.
Interesting. From the link you provided, numbering from top to bottom, a = aligned, n = not aligned, the different browsers show:
ie6 1 n, 2 n, 3 n
ie7 1 a, 2 n, 3 n
ie8 1 a, 2 n, 3 a
ff2 1 a, 2 n, 3 a
ff3 1 a, 2 n, 3 n
saf 1 a, 2 a, 3 a
chr 1 a, 2 a, 3 a
Removing the vertical align fixes it in ff2 but not ff3.
IE does not support inline-block. That may be causing some of the browser differences.
I don't know why there is such a big difference between safari/chrome, ff2 and ff3.
I had a go at styling the button from scratch. The following CSS is what I came up with. It has the advantage that the adjacent text to the button does not need to be wrapped in any additional elements. It works fine in the latest version of Internet Explorer, Firefox, and Safari. Firefox 2 doesn't correctly size the button height, and IE 6 and 7 each butcher it in their own special ways.
Here's a live example of this code.
.yui-button {
display: inline-block;
background: transparent url(http://yui.yahooapis.com/2.7.0/build/assets/skins/sam/sprite.png) repeat-x scroll 0 0;
border-color: #808080;
border-style: solid;
border-width: 1px 0;
margin: auto 0.25em;
}
.yui-skin-sam .yui-button .first-child {
display: inline-block;
border-color: #808080;
border-style: solid;
border-width: 0 1px;
margin: 0 -1px;
}
.yui-skin-sam .yui-button button {
background-color: transparent;
border: medium none;
margin: 0;
min-height: 2em;
padding: 0 10px;
}
You could try using a negative margin-bottom to pull the button down vertically; if you use the same value as the padding that's on the text within the button, or on the button itself, it might be positioned properly.
I'm at work, and writing this on IE6 (I know, I know...), so I'm not really able to look too closely (no Firebug, etc -not an IT professional), but if you used vertical-align: baseline; or something similar it positions the element, not the text within it, to the baseline of the surrounding text.
You could, alternately, try using line-height: $height; where $height is equal to the vertical height of the button; which forces the surrounding text to be vertically centered within that height. No guarantees, but it might/should work.
To have the button aligned with the text next to it:
Make sure the button (a div in this case) is inline-block. This is really the hard part, so I did a little write-up on how to get IE6+ and other browsers to honor the inline-block.
Add a vertical-align: middle on the button and the text.

What is the difference between outline and border CSS properties?

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".

Resources