Why CSS text-align property centers block-level content? - css

I’ve got 2 questions.
1) Is the text inside the navigation links centered because I set the value of the display property of those links(a tags) to block and now it’s basically the same thing as if I was centering text inside a p element?
2) I set the display property of i elements(font awesome icons) to block too, so why are these elements centered as well? If you change the display property on the i elements to table, then these icons are not being centered. Shouldn’t block value behave the same as table in this case? As far as I know I can only use text-align to align inline and inline-block elements. So why is this working?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Text-align</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<style>
.cf:before,
.cf:after {
content: "";
display: block;
}
.cf:after {
clear: both;
}
body {
margin: 0;
font: 16px/1 sans-serif;
}
nav {
height: 120px;
background-color: #f2f2f2;
padding: 0 5%;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
float: left;
color: #a6a6a6;
border-left: 1px solid #a6a6a6;
}
li:last-child {
border-right: 1px solid #a6a6a6;
}
li:hover {
color: #de5728;
}
a {
display: block;
text-decoration: none;
color: inherit;
font-size: 10px;
text-transform: uppercase;
padding: 37px 0;
width: 136px;
text-align: center;
}
nav a .fa {
display: block;
font-size: 36px;
}
</style>
</head>
<body>
<nav>
<ul class="cf">
<li>
<a href="#">
<i class="fa fa-shield"></i> Domov
</a>
</li>
<li>
<a href="#">
<i class="fa fa-leaf"></i> Portfolio
</a>
</li>
<li>
<a href="#">
<i class="fa fa-bolt"></i> O nas
</a>
</li>
<li>
<a href="#">
<i class="fa fa-trophy"></i> Kontakt
</a>
</li>
</ul>
</nav>
</body>
</html>

Yes. Block containers can have text-align applied, which aligns their content.
Block-level elements in normal flow take up the full width of their containing block, which in your example is the width of the content box of the li elements.
The content box width of the element is calculated according to this equality:
'margin-left' + 'border-left-width' + 'padding-left' +
'width' +
'padding-right' + 'border-right-width' + 'margin-right' =
width of containing block
In your example, the margins and paddings resolve to 0, and the borders to 0 or 1 pixels. The containing block is provided by the <a> element and the remainder of its width is the content box width of the <i> element when it is display:block.
The text-align property is inherited, so the <i> element takes on the alignment and centres its content within the width of its content box, the content for the <i> element being provided by fontawesome via the :before pseudo-element.
Table elements are block-level, but they resolve the equality differently. Instead, the width of their content box is shrink-to-fit, and any remaining width of the containing block is, in your example, given to the right margin instead.
This puts the table over to the left side of its container, and the content (again the generated content from fontawesome) goes tightly inside that. The anonymous table cell created inside the table still inherits the text-align setting, but there's no space either side of the content for it to move in. So it too appears to be on the left side of the floated <li> element whose width is determined by tightly wrapping the <a> element inside it.

Yes. block level (and inline-block with a width) can have text-align:center applied.
the i elements will inherit from their parent, the a tag, and so will also be centered.
Display block and table are very different to each other in that the child elements are rendered differently, i.e children of a table would likely be display:table-cell.
Also, text-align really makes no sense on inline elements.

Related

text-overflow ellipsis in breadcrumb - height

I have breadcrumb menu with a long category name. When I add a text-overflow ellipsis to the last category name, the two breadcrumbs before are deeper then the last one. How to get a equal height in the middle of the breadcrumb.
I made a Jsfiddle:
https://jsfiddle.net/0rdeyhst/
<div itemprop="breadcrumb" itemscope="" itemtype="http://schema.org/BreadcrumbList" id="breadcrumbs">
<span itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem" class="icon-home"><a itemprop="item" href="#" accesskey="h"><span itemprop="name">Home</span><meta itemprop="position" content="1"></a></span>
» <span itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem"><span itemprop="name">Caegory</span><meta itemprop="position" content="2"></span> » <span itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem"><h1><span itemprop="name">This is a long category name adsfl lkajdlfjasldfjasdfasdf asdfadf</span></h1><meta itemprop="position" content="3"></span>
</div>
thank you
By default, browsers set margins to tags, and overflow hidden causes some text alignment problems. So you should add these 2 properties into your CSS
#breadcrums h1 {
margin: 0;
vertical-align: middle;
}
You should add the following css-rules to your H1-tag:
h1 {
margin: 0;
vertical-align: top;
}
The h1 tag is displayed block by default, while your span elements are displayed inline.
the display: inline does not respect any margins and or paddings that you have added to the element, however the display: inline-block does.
if you change the display property of your #breadcrumbs h1, This problem is solved. But because the display: inline won't respect the width of the h1 element your overflow: ellipsis will break.
Therefore, I recommend to use flexbox.
#breadcrumbs {
display: flex;
align-items: center;
}
I highly recommend you to read this guide to understand what is happening:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/

alignment box for inline-block non-replaced elements

Please run the demo:
* {
margin: 0;
padding: 0;
}
.body {
font-family: Microsoft Yahei;
font-size: 16px;
background-color: lightblue;
height: 400px;
width: 400px;
line-height: 2;
vertical-align: baseline;
}
.body span {
background-color: pink;
}
.body .inline-block {
display: inline-block;
background: orange;
height: 50px;
}
.inline-block.text {
vertical-align: text-top;
}
<div class="body">
<span>
words-g words words-g
<span class="inline-block text">with inline-block box child</span> words-g w
</span>
</div>
The point is that I set
.inline-block.text {
vertical-align: text-top;
}
According to the specification:
In the following definitions, for inline non-replaced elements, the box used for alignment is the box whose height is the 'line-height' (containing the box's glyphs and the half-leading on each side, see above). For all other elements, the box used for alignment is the margin box.
and in the section 'line-height':
On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element. The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties. We call that imaginary box a "strut." (The name is inspired by TeX.).
So,in this case,.inline-block.textis a
block container element whose content is composed of inline-level elements
whose height is 50px and line-height is 32px
also is an inline non-replaced elements
And here is my question:
the box used for alignment is the box whose height is the 'line-height'
What is the above box point at in this case for .inline-block.text?
As the demo shows,I think it is the box with height 50px. However,the box's height is not the line-height which conflicts with the specification above. So,I was confused and don't understand the above sentence in the specification.
And if you think the above box is the box with height 50px,how do you explain the fact that height 50px is not the line-height 32px?
Please notice:
I just want to understand this sentence which is the box used for alignment is the box whose height is the 'line-height',so I can understand the vertical-align better.
I am not asking for a specific solution.
Whatever thanks for your help!
The statement
for inline non-replaced elements, the box used for alignment is the box whose height is the 'line-height'
does not apply to inline-blocks. Inline-blocks are not inline elements. Inline elements are elements with display: inline, and generate inline boxes. Inline-blocks are not inline boxes, but inline-level (the "-level" part is important!) block container boxes. Therefore, the statement
For all other elements, the box used for alignment is the margin box.
applies instead, which results in vertical-align: text-top causing the top outer edge of the inline-block to align with the top of the line box.
Any part of the specification that is said to apply to inline elements does not apply to inline-blocks.
I guess you are confusing about the reference of the alignment (it aligns relatively to what?).
I will try to explain this with easy words. When using vertical-align with an element a you align it relatively to its parent element b whataver is the height of a (b is the reference). Using correct words it's like this:
The vertical-align property can be used in two contexts:
To vertically align an inline element's box inside its containing line
box. For example, it could be used to vertically position an <img> in
a line of text.ref
So the a element is the inline element's box and the b element is the containing line box and the height of b is defined by it's line-height as you already read in the specification.
Now let's consider your code and add properties step by step.
Initially let's remove the inline-block
.body {
font-family: Microsoft Yahei;
font-size: 16px;
background-color: lightblue;
}
.body span {
background-color: pink;
}
.body .inline-block {
background: orange;
}
.inline-block.text {
vertical-align: text-top;
}
<div class="body">
<span>
words-g
<span class="inline-block text">inline-block</span> words-g w
</span>
</div>
As you can see the inner span has the same height/line-height as the outer span and both are using the same font-family. So logically we see nothing when using text-top as vertical alignment.
Now let's add line-height:2 to the container:
.body {
font-family: Microsoft Yahei;
font-size: 16px;
background-color: lightblue;
line-height:2;
}
.body span {
background-color: pink;
}
.body .inline-block {
background: orange;
}
.inline-block.text {
vertical-align: text-top;
}
<div class="body">
<span>
words-g
<span class="inline-block text">inline-block</span> words-g w
</span>
</div>
In this situation, both span will inherit the line-height:2 thus the computed value will be 32px (2 * font-size) and this will make the top reference different from text-top. To remind about this, here is a figure I shared with your beforeref:
And if we read the definition about the value text-top of vertical-align:
Aligns the top of the element with the top of the parent element's
font.
So the top of the inner span will align with the text-top of the outer span, that's why it moved to the bottom. Then the height of the main container .body will not be equal to 32px but it will be bigger because it will consider the movement of inner span (we will have 37px).
Now let's add inline-block to the inner element:
.body {
font-family: Microsoft Yahei;
font-size: 16px;
background-color: lightblue;
line-height:2;
}
.body span {
background-color: pink;
}
.body .inline-block {
background: orange;
}
.inline-block.text {
vertical-align: text-top;
display:inline-block;
}
<div class="body">
<span>
words-g
<span class="inline-block text">inline-block</span> words-g w
</span>
</div>
The first thing you will notice is that the text didn't move BUT the orange background is covering a bigger height. This is because our element will behave as block container and this height is the line-height of the text (32px) which is also the distance between the top and bottom in the image above (Initially it was covering from text-bottom to text-top).
It's also like the blue background of the .body element since this one is a block element. Try to make the .body element inline and see what will happen.
Now you can also add a specific height to the element and nothing will change because we align relatively to the parent element. You can also play with all the vaues of vertical-align to see the different behaviors:
.body {
font-family: Microsoft Yahei;
font-size: 16px;
background-color: lightblue;
line-height:2;
margin:5px;
}
.body span {
background-color: pink;
}
.body .inline-block {
background: orange;
}
.inline-block.text {
display:inline-block;
height:50px;
}
<div class="body">
<span>
Align the
<span class="inline-block text" style="
vertical-align: text-top;">top of this</span> with text-top
</span>
</div>
<div class="body">
<span>
Align the
<span class="inline-block text" style="
vertical-align: top;">top of this</span> with top
</span>
</div>
<div class="body">
<span>
align the
<span class="inline-block text" style="
vertical-align: text-bottom;">bottom of this</span> with text-bottom
</span>
</div>
<div class="body">
<span>
align the
<span class="inline-block text" style="
vertical-align: bottom;">bottom of this</span> with bottom
</span>
</div>

CSS Header style not applied to children

I am beginner to UI World, trying to style and arrange html components in one of my example, but I could not see the style applied for all the children of HTML header component. Here is what I have tried Demo in JsFiddle
.page_header_style {
border: 1px solid blue;
}
.title_style {
text-align:center;
}
ul {
list-style: none;
}
li {
display: block;
}
.user_style {
float: right;
margin-top: 0px;
}
<header class="page_header_style">
<div>
<div class="title_style">Main Title</div>
<div>
<ul class="user_style">
<li>Welcome Srk</li>
<li>Logout</li>
</ul>
</div>
</div>
</header>
I would like to see the second div i.e., Welcome message & a list in the same line of the title, keeping the title at the center.
In order to make the "title" text in the center viewport wise, you can make the "user info" as position:absolute, so it will be out of the normal content flow. See the demo below.
.page_header_style {
border: 1px solid blue;
padding: 20px 0;
position: relative;
}
.title_style {
text-align:center;
}
.user_style {
position: absolute;
top: 10px;
right: 10px;
list-style: none;
padding: 0;
margin: 0;
}
<header class="page_header_style">
<div>
<div class="title_style">Main Title</div>
<div>
<ul class="user_style">
<li>Welcome Srk</li>
<li>Logout</li>
</ul>
</div>
</div>
</header>
JSFiddle Demo: http://jsfiddle.net/wt5f81qz/
You should apply float: left to the .title_style, and put a clearing element (clear:both) on the bottom of inner content of .page_header_style
Here: http://jsfiddle.net/r1af39at/
Kosturko answer regarding clearfixes
You can alternatively use the clearfix solutions with is better than adding clear:both to an element, because in some case you'd need extra markup to apply clear:both.
The both clearfixes are applied to the immediate parent containing the floating elements.
Clearfix 1: is just to apply overflow:hidden; this works but can cause styling issues if say you wanted something to flow outside the parent using position absolute for example.
The better clearfix is to use the micro clearfix, best applied using a CSS preprocessor.
Good luck
By default, div elements have the display: block; attribute. Without other css styling, browsers will render them below the last block element. Try using the display: inline-block; as this will treat each div as an inline element, but treat its contents as the contents of a block element.
For example, the following css will display the main title and both list elements on the same line.
li{
display: inline-block;
}
div {
display: inline-block;
}
See w3schools's page on the display property for more on this.

List bullet alignment changes when LI contains a block-level empty element

I hope someone can explain this odd CSS issue I'm encountering.
I have an empty element (think <img> or <input>) inside a li. When I change the display style on the empty element to "block", the alignment of the bullet on the li changes. If I do the same thing with a non-empty element (<span>, say), the bullet alignment does not change.
The bullet alignment changes even if the empty element is inside another block-level element (<div>).
Here are two examples on JSFiddle:
Using an <img> element
Using a <span> element
And screenshots of the results (<img> on the left, <span> on the right:
I have two questions:
Why do the bullets do this?
How can I make the bullets in the <img> example line up the same way as in the <span> example?
For reference, the stylesheet:
ul { background: lightgreen; width: 100px; padding-left: 50px; }
div { background: lightblue; }
img { background: lightcoral; }
li { background: lightyellow; }
img { width: 50px; height: 50px; }
img[rel] { display: block; }
And the HTML:
<ul>
<li>
<div><img rel></div>
</li>
</ul>
<ul>
<li>
<div><img></div>
</li>
</ul>
<ul>
<li>
<div><img rel></div>
<p> ! </p>
</li>
</ul>
<ul>
<li>
<div><img></div>
<p> ! </p>
</li>
</ul>
(I know my <img> elements don't have src attributes. This is just for illustration purposes. BTW, it still works in Google Chrome, but not Firefox.)
It is an issue with alignment for images, they default to the bottom alignment which causes the list items to move with them. In order to fix this problem, add this to the image tag:
img {
display: inline-block;
vertical-align: middle;
}
The display: inline-block is the only display type that will allow vertical align to work.

Why does my list's background-color disappear when I float its list elements?

The moment I float my unordered-list element...the background color fails. Why?
<style type="text/css">
.bkgrd-blue { background-color: #094AB2; }
.application-bar { color: #FFFFFF; }
.application-bar ul { }
.application-bar ul.control-bar { list-style: none outside none; margin: 0; overflow: visible; padding: 0; }
.application-bar ul.control-bar.branding { float: left;}
</style>
<div class="application-bar bkgrd-blue">
<ul class="control-bar">
<li>
This is working!
</li>
</ul>
</div>
<div class="application-bar bkgrd-blue">
<ul class="control-bar branding">
<li>
The moment I float this...it fails! Why?
</li>
</ul>
</div>
Floating an element removes it from the normal document flow so containers don't expand - that is, the containing div has 0 height.
To fix this you need to clear the float. You can either:
set overflow: hidden on the div
float the div
add an element after the floated list with clear:both - this could be done using the :after pseudo-element
Here's a demo using the first solution: http://jsfiddle.net/FSH4Y/
I added:
.application-bar {
color: #FFFFFF;
overflow: hidden;
}
Here's some more info on this issue: CSS Tricks: All About Floats - have a look at the section called The Great Collapse
You need to clear under the list, usually I add a div like
<div style='clear:both;'></div>
This will allow the floated element's parent to properly calculate it's height.
You need to float the containing div with the background in it as well. As soon as you float the inner ul, the containing div effectively has no content so ends up with a height of 0.

Resources