In IE, Edge, and Safari, a <th> descendant of a <li> is center-justified.
In Chrome, Firefox, and Opera, it's left-justified.
According to W3C Rendering recommendations (italics mine):
User agents are expected to have a rule in their user agent stylesheet
that matches th elements that have a parent node whose computed value
for the 'text-align' property is its initial value, whose declaration
block consists of just a single declaration that sets the 'text-align'
property to the value 'center'.
The italicized section states that a <th> element should be centered if its parent's text-align property hasn't been changed.
That's not the case for <th> descendants of <li> in Chrome, Firefox, and Opera. Am I correct in assuming that they are ignoring W3C recommendations?
(The problem is easily overcome by using th {text-align: center;}, so I don't need a solution.)
Edit
I've received a couple of good explanations for the behavior, but the answers are unsatisfactory – through no fault of the posters.
I think the intent of the W3C is that <th> elements should be centered unless they include or inherit a different explicit text-align style. It doesn't make sense that <th> elements should be left-justified due to a convoluted cascading inheritance of implicit styles.
It seems to hinge on what W3C means by "its initial value" in the quote. The "initial value" of a <li>'s text-align property is match-parent, which is apparently different from text-align: initial.
Hopefully the W3C will clarify this in the future. In the meantime, th {text-align: center;} solves the problem.
Example:
th, td {
border: 1px solid #ddd;
}
<ol>
<li>
<table>
<tr>
<th>This is a Lorem Ipsum<br>test</th>
<th>Another header
</tr>
<tr>
<td>ABCDEFG HIJKLMNOP QRSTUV WXYZ
<td>More
</tr>
</table>
</li>
</ol>
your issue is that li is by default text-align: match-parent (at least on Firefox), which mean the li are text-align:left (if direction is ltr otherwise is text-align:right) so if you change li to text-align:initial the th will work as you expect
match-parent
Similar to inherit, but the values start and end are calculated according the parent's direction and are replaced by the
adequate left or right value.
th,
td {
border: 1px solid #ddd;
}
li {
text-align: initial
}
<ol>
<li>
<table>
<tr>
<th>This is a Lorem Ipsum
<br>test</th>
<th>Another header
</tr>
<tr>
<td>ABCDEFG HIJKLMNOP QRSTUV WXYZ
<td>More
</tr>
</table>
</li>
</ol>
No, they are not ignoring W3C. From the quote in your question,
a parent node whose computed value for the 'text-align' property is its initial value
But that's not the case. The initial value for text-align is start, which computes to start. But <li> elements are styled with text-align: match-parent, which computes to left since the <ol> has direction: ltr. Even though start behaves like left because the <li> also has direction: ltr, they are different values. That's why the th is not centered.
Note both start and match-parent are recent additions. Possibly the th becomes centered on browsers which don't support them yet.
If you use li { text-align: initial; } then th th is centered.
th, td {
border: 1px solid #ddd;
}
li {
text-align: initial;
}
<ol>
<li>
<table>
<tr>
<th>This is a Lorem Ipsum<br>test</th>
<th>Another header
</tr>
<tr>
<td>ABCDEFG HIJKLMNOP QRSTUV WXYZ
<td>More
</tr>
</table>
</li>
</ol>
Related
Is there any guidance on when to choose aria-describedby instead of aria-labelledby?
Reading the MDN guidance on the two attributes, I get the feeling they are similar and interchangeable.
Both seem to suggest that they can be used for input labels and other content but many compliance tools do not seem to like aria-describeby on input tags. I hate applying a particular attribute blindly just because a tool says I should and I would prefer to know something concrete about the when and why
Here are the entries on MDN regarding the two aria attributes in question:
aria-labelledby attribute
aria-describedby attribute
They are indeed very similar, there is one key distinction.
aria-labelledby
aria-labelledby will overwrite any existing labelling including any semantically derived label.
For example if you had a <button> and used aria-labelledby the button text would be overwritten by the first item you listed as the label.
In the following example if you tab to the button (using the mouse over will read the button text in some screen readers) it will read "first label" then "Further information" instead of "this text will not be read".
<button aria-labelledby="lbl1 lbl2">This text will not be read</button>
<p id="lbl1">first label</p>
<p id="lbl2">Further information</p>
aria-describedby
aria-describedby on the other hand will read the linked information as additional information. It will read this after the button semantically derived information.
So in the below example it will read "This text will now be read", "first label" then "Further information". Yet again you need to focus the button (not mouse over) to see this behaviour.
<button aria-describedby="lbl1 lbl2">This text will now be read</button>
<p id="lbl1">first label</p>
<p id="lbl2">Further information</p>
Limitations
Warning - support for aria-labelledby and aria-describedby is really not as good as you might think.
If information is truly important (i.e. the element will not make sense without it) then you should revert to using visually hidden text instead.
I have a Stack Overflow answer on the class you should use for visually hidden text instead of the built in sr-only class in most libraries.
Please note there are certain times you cannot use this (i.e. within a <select>s <option>, but for essential information this is the only 100% supported way to do it (all the way back to IE6)
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<button>This text will now be read <span class="visually-hidden">,first label</span> <span class="visually-hidden">,Further information</span></button>
Regardless of technical differences, or level of support (which Graham has covered very well), there is a semantic difference. A label is not a description. In the MDN pages you linked to, it states:
A label provides essential information about an object, while a
description provides extended information that the user might need.
The key semantic difference is the word "extended", or as w3c puts it:
a label should be concise, where a description is intended to provide
more verbose information
So, labels are used for controls like "Quit" or "Cancel", or brief text labels, such as product names, whereas descriptions tend to be lengthier, containing more detail, or providing a higher-level, general interpretation of the content.
Example: I've recently been using aria-labelledby to refer to a legend. The legend is just a list, where each list item has an id. Then, elsewhere on the same page, in a chart or table, or even another list, I use aria-labelledby to point to the corresponding legend item. This decouples the legend from the data, and allows the same legend to be reused on multiple charts, table headers, figures, diagrams or whatever.
As an added bonus, you can CSS select items with a given aria-labelledby value (using an attribute selector such as th:[aria-labelledby='tableLabelFurry']) and style all elements that use this label in a consistent way.
Here's some sample code which shows two separate tables, whose headers are derived from a legend:
* {
box-sizing:border-box;
}
html {
background:gray;
}
body {
padding: 1.5rem;
background:white;
font-family:sans-serif;
}
main[role='main'] {
width: 10rem;
max-width: 18rem;
padding: 1.5rem;
margin: auto;
background:silver;
}
table th, table td {
padding:1em;
width:10em;
border:1px solid pink;
}
ol {
margin-left:10em;
}
ol li {
display:inline-block;
padding:1em;
width:10em;
}
<h1>Two tables sharing headers (legend implementation)</h1>
<ol id="legend">
<li id="tableLabelNumLegs">Legs</li>
<li id="tableLabelFamily">Order</li>
<li id="tableLabelFurry">Furry?</li>
</ol>
<h2>woot</h2>
<table>
<caption>Common Animals</caption>
<tbody>
<tr>
<th scope="col">Name</th>
<th scope="col" aria-labelledby="tableLabelNumLegs"></th>
<th scope="col" aria-labelledby="tableLabelFamily"></th>
<th scope="col" aria-labelledby="tableLabelFurry"></th>
</tr>
<tr>
<th scope="row">Flea</th>
<td>6</td>
<td>Siphonaptera</td>
<td>A bit</td>
</tr>
<tr>
<th scope="row">Frog</th>
<td>4</td>
<td>Anura</td>
<td>No</td>
</tr>
</tbody>
</table>
<hr />
<table>
<caption>Rare animals</caption>
<tbody>
<tr>
<th scope="col">Name</th>
<th scope="col" aria-labelledby="tableLabelNumLegs"></th>
<th scope="col" aria-labelledby="tableLabelFamily"></th>
<th scope="col" aria-labelledby="tableLabelFurry"></th>
</tr>
<tr>
<th scope="row">Tiger</th>
<td>4</td>
<td>Carnivora</td>
<td>Yes</td>
</tr>
<tr>
<th scope="row">Panda</th>
<td>4</td>
<td>Carnivora</td>
<td>Yes</td>
</tr>
</tbody>
</table>
aria-describedby might instead be used to give a general description of the content.
According to the spec, both attributes can contain references to more than one id, but I would recommend careful testing with a range of ATs and browsers if you intend to do this.
Can anyone shed some light on this?
HTML:
<table>
<tr>
<td></td>
<td class="size20">
<div>Div 1 is font-size: 20px</div>
<table>
<tr>
<td>
<div>Div 2 should be font-size 20px because of inheritance and specificity</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
CSS:
.size20 {
font-size: 20px;
}
td {
font-size: 10px;
}
http://codepen.io/geoyws/pen/wGqqMB
The inherited value is only used when the cascade doesn't resolve a value for the given element. See "specified values" in the spec.
Your inner div has a font size of 10 pixels because it inherits from the inner td, which itself has a font-size: 10px declaration. The value that's inherited from all of the inner td's ancestors up to .size20 is ignored since the cascade has already determined a value for that td based on that declaration. Specificity is completely irrelevant because the .size20 selector doesn't even match the inner td in the first place. The fact that you're dealing with tables is also irrelevant.
Everything is working as designed. There is no flaw in either the specification or browsers as you suggest.
In css the last class effect will be overlaped by previous. It correctly inherits the size20 class but when it reaches td it overlaps the class size20 by td class.
If you again need size20 effect, then you need to add that class there. And that supress the effect of td, that's what happened in first div
I have this piece of HTML that I want to style.
The html is a table (and actual table), which I want to give a border.
The element also had a :before pseudo-element, which I use to put a small triangle in the top corner.
The JSFiddle is here.
I hope it makes sense. I stripped down the markup and the CSS as much as possible, because it's actually a small part of a big site.
http://jsfiddle.net/GolezTrol/28yDb/2/
Now the problem is that the combination of having 2 columns, having border-collapse: collapse; on the table and the :before pseudo element, cause the top border of the element to partially disappear. It's only there for the length of the first column.
You would assume that it is the pseudo element that is on top of the border, but this element is very small, and as far as I can tell, this could not be the problem. I added visibility: hidden; to the pseudo element to be sure, and I can tell that the triangle is gone, but the border is still incomplete.
Unfortunately I cannot change the markup, since this is outputted by MediaWiki, but I do have full control over the CSS.
The HTML:
<div id="globalWrapper">
<div id="column-content">
<div class="thumb tright">
<table class="infobox vcard" style="">
<tbody>
<tr>
<th colspan="2" class="fn org" style=""> Example text</th>
</tr>
<tr>
<th>Row head</th>
<td>Content</td>
</tr>
The CSS:
/* Generic table styling */
table {
border-collapse: collapse;
/*border-spacing: 0;*/ }
/* The box */
.thumb.tright table.infobox.vcard {
border: 3px solid #fae104;
position: relative;
}
/* Triangle */
.thumb.tright table.infobox.vcard:before {
content: "";
position: absolute;
width: 0;
height: 1px;
border-top: 5px solid transparent;
top: -7px;
border-left: 10px solid #555;
visibility: hidden;
right: -1px; }
I already found out that it works when I remove border-collapse: collapse;, but I'm not sure that is a proper solution, and even if it is, I would really like an explanation of what is going on.
Btw. I got this problem both in Chrome 29 and in Internet Explorer 10. Haven't tested other browsers.
Update
Instead of using -or not using- 'border-collapse' to fix the problem, I found out that this also works:
.thumb.tright table.infobox.vcard tbody {
display: block;
}
So the table itself is still a table, the pseudo element is still on the table, as is the border, positioning etc. The tbody, which was unstyled before, is now a block and the problem is solved in both browsers. I found this by trial and error, and still wouldn't know the reason behind it.
Updated fiddle: http://jsfiddle.net/GolezTrol/28yDb/9/
Being a newbie to StackOverflow and jsFiddle I updated the Fiddle with that I think is the solution. I didn't change the CSS except for moving the pseudo class from the table itself to the table header, and changing it into :after. Works for me in Firefox and Chrome!
/* Triangle */
.thumb.tright table.infobox.vcard th:after { }
Border-collapse: seperate is not supported in IE8 but I think this will be.
edit: nevermind ;)
It is a problem only occur on Webkit browsers I think. It can be considered a "browser bug" imo.
th should be inside thead, not tbody:
<thead>
<tr>
<th colspan="2" class="fn org" style=""> Example text</th>
</tr>
</thead>
<tbody>
<tr>
<th>Row head</th>
<td>Content</td>
</tr>
<tbody>
And I think this is the correct solution. You are putting an element where it is not advised to be, so it should be normal for a problem to occur.
Edit: as thirtydot pointed out, changing the th to td doesn't change the result. It only work when I moved the th to the thead section. At this point I am at a loss, I can't find a way to solve this.
But at least I think I can provide my speculation on the cause of this problem:
:before create a pseudo element inside the target element. What kind of element is unknown to me, but I suspect that the browser create a td. If that is true, then after rendering your html should look like this:
<table>
<td></td> /*the pseudo element*/
<tbody>
<tr>
<th colspan="2" class="fn org" style=""> Example text</th>
</tr>
<tr>
<th>Row head</th>
<td>Content</td>
</tr>
<tbody>
</table>
Needless to say this look weird. And if you try the above html out you can see the result is similar to your problem. border-collapse:collapse will merge 2 borders together where there are 2 cells next to each other, or a cell is next to the table's border. So I suspect in this case, the pseudo element - which doesn't have appropriate colspan - last only 1 column, the rest of that row is empty: nothing's there. This is where I think caused the bug: because there's no cells next to the table border there, no border is created at all.
The real reason may be a little bit more complicated ("why doesn't the bug occur when I put in a thead?"), but I think my answer is not too far off the mark. :)
The only reasonable explanation I can think of is pseudo-element :before not being compatible with the display: table of the table in collapsed mode. That is why border-collapse: separate; solves the problem. Suddenly, the browser can display the top border not caring about the pseudo element.
If you look closely, you can clearly see that the missing part of the border is the width of the second column. If you change it to after pseudo element, the border is missing in the bottom-right corner, again due to the fact that the borders of the table and the pseudo-element are collapsed.
If you change the border-bottom of th to be 3px solid red in collapsed mode, the th overpowers the table and the border is red. I presume, the power of after and before follow the same rule. It would be nice if someone who knows the specs better came to answer that.
Thinking this way, I do not believe there can be any other solution than:
using separate borders
putting the pseudo element on the parent div
What I inspected is that the pseudo element is actually rendered as block and can be change to table and list-item. However, none of these change the behaviour.
Very random stuff that is actually compliant with Av Avt's answer about where the pseudo element is rendered in regards of the DOM.
If I append the :beofre like this, the border stays:
.thumb.tright table.infobox.vcard tr:before
Obviously, it creates as many new pseudo element as there are rows.
This question already has answers here:
CSS: how do I create a gap between rows in a table?
(12 answers)
Space between two rows in a table?
(30 answers)
Closed 3 years ago.
I have a table containing many rows. Some of these rows are class="highlight" and signify a row that needs to be styled differently and highlighted. What I'm trying to do is add some extra spacing before and after these rows so they appear slightly separated from the other rows.
I thought I could get this done with margin-top:10px;margin-bottom:10px; but it's not working. Anyone knows how to get this done, or if it could be done? Here's the HTML and I've set the 2nd tr in the tbody to class highlight.
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value1</td>
<td>Value2</td>
</tr>
<tr class="highlight">
<td>Value1</td>
<td>Value2</td>
</tr>
<tr>
<td>Value1</td>
<td>Value2</td>
</tr>
<tr>
<td>Value1</td>
<td>Value2</td>
</tr>
</tbody>
</table>
The border-spacing property will work for this particular case.
table {
border-collapse:separate;
border-spacing: 0 1em;
}
Reference.
Table rows cannot have margin values. Can you increase the padding? That would work. Otherwise you could insert a <tr class="spacer"></tr> before and after the class="highlighted" rows.
You can't style the <tr>s themselves, but you can give the <td>s inside the "highlight" <tr>s a style, like this
tr.highlight td {
padding-top: 10px;
padding-bottom:10px
}
This isn't going to be exactly perfect though I was happy to discover that you can control the horizontal and vertical border-spacing separately:
table
{
border-collapse: separate;
border-spacing: 0 8px;
}
line-height can be the possible solution
tr
{
line-height:30px;
}
I know this is kind of old, but I just got something along the same lines to work. Couldn't you do this?
tr.highlight {
border-top: 10px solid;
border-bottom: 10px solid;
border-color: transparent;
}
Hope this helps.
First of all, don't try to put a margin to a <tr> or a <td> because it won't work in modern rendering.
Solution 1
Although margin doesn't work, padding does work :
td{
padding-bottom: 10px;
padding-top: 10px;
}
Warning : This will also push the border further away from the element, if your border is visible, you might want to use solution 2 instead.
Solution 2
To keep the border close to the element and mimic the margin, put another <tr> between each of your reel table's <tr> like so :
<tr style="height: 20px;"> <!-- Mimic the margin -->
</tr>
A way to mimic the margin on the row would be to use the pseudo selector to add some spacing on the td.
.highlight td::before, .highlight td::after
{
content:"";
height:10px;
display:block;
}
This way anything marked with the highlight class will be separated top and bottom.
https://jsfiddle.net/d0zmsrfs/
Because margin is ignored on tr, I usually use a workaround, by setting a transparent border-bottom or border-top and setting the background-clip property to padding-box so the background-color does not get painted underneath the border.
table {
border-collapse: collapse; /* [1] */
}
th, td {
border-bottom: 5px solid transparent; /* [2] */
background-color: gold; /* [3] */
background-clip: padding-box; /* [4] */
}
Makes sure cells share a common border, but is completely optional. The solution works without it.
The 5px value represents the margin that you want to achieve
Sets the background-color of your row/cell
Makes sure the background get not painted underneath the border
see a demo here: http://codepen.io/meodai/pen/MJMVNR?editors=1100
background-clip is supported in all modern browser. (And IE9+)
Alternatively you could use a border-spacing. But this will not work with border-collapse set to collapse.
You might try to use CSS transforms for indenting a whole tr:
tr.indent {
-webkit-transform: translate(20px,0);
-moz-transform: translate(20px,0);
}
I think this is a valid solution. Seems to work fine in Firefox 16, Chrome 23 and Safari 6 on my OSX.
Here's a neat way I did it:
table tr {
border-bottom: 4px solid;
}
That will add 4px of vertical spacing between each row. And if you wanted to not get that border on the last child:
table tr:last-child {
border-bottom: 0;
}
Reminder that CSS3 pseudo-selectors will only work in IE 8 and below with selectivizr.
I gave up and inserted a simple jQuery code as below. This will add a tr after every tr, if you have so many trs like me.
Demo: https://jsfiddle.net/acf9sph6/
<table>
<tbody>
<tr class="my-tr">
<td>one line</td>
</tr>
<tr class="my-tr">
<td>one line</td>
</tr>
<tr class="my-tr">
<td>one line</td>
</tr>
</tbody>
</table>
<script>
$(function () {
$("tr.my-tr").after('<tr class="tr-spacer"/>');
});
</script>
<style>
.tr-spacer
{
height: 20px;
}
</style>
A hack to give the appearance of margins between table rows is to give them a border the same color as the background. This is useful when styling a 3rd party theme where you can't change the html markup. Eg:
tr{
border: 5px solid white;
}
add a div to the cells that you would like to add some extra spacing:
<tr class="highlight">
<td><div>Value1</div></td>
<td><div>Value2</div></td>
</tr>
tr.highlight td div {
margin-top: 10px;
}
You can create space between table rows by adding an empty row of cells like this...
<tr><td></td><td></td></tr>
CSS can then be used to target the empty cells like this…
table :empty{border:none; height:10px;}
NB: This technique is only good if none of your normal cells will be empty/vacant.
Even a non-breaking space will do to avoid a cell from being targetted by the CSS rule above.
Needless to mention that you can adjust the space's height to whatever you like with the height property included.
Another possibility is to use a pseudo selector :after or :before
tr.highlight td:last-child:after
{
content: "\0a0";
line-height: 3em;
}
That might avoid issues with browser that don't understand the pseudo selectors, plus background-colors are not an issue.
The downside is however, that it adds some extra whitespace after the last cell.
For what is worth, I took advantage that I was already using bootstrap (4.3), because I needed to add margin, box-shadow and border-radius to my row, something I can't do with tables.
<div id="loop" class="table-responsive px-4">
<section>
<div id="thead" class="row m-0">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div id="tbody" class="row m-0">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
</section>
</div>
On css I added a few lines to mantain the table behavior of bootstrap
#media (max-width: 800px){
#loop{
section{
min-width: 700px;
}
}
}
add this style before the class="highlighted"
padding-bottom and
display is inline-table
As it turns out I don't know CSS.
I ran into a brick wall after using Eric Meyer's CSS reset (http://meyerweb.com/eric/tools/css/reset/)
I have a table with this style
table.home_right_top, .home_right_top table, .home_right_top
{
background-color: #F2F2F2;
width: 100%;
padding: 10px 20px 15px 20px;
}
but the padding is not applied to the table at all and I cannot figure out why. I am happy that I see the same behavior on all the browsers including IE7 and IE8 but I don't see any padding. Can someone please tell me what I am doing wrong here?
Thanks.
EDIT
This is my table
<table class="home_right_top" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="blueHeading14 heading_padding_right" style="width: 64px">Products</td>
<td class="rpt_stroke" style="width: 280px"> </td>
</tr>
</tbody>
</table>
The problem isn't the reset, it's that the W3 CSS property spec states that padding can be applied to:
all elements except table-row-group,
table-header-group,
table-footer-group, table-row,
table-column-group and table-column
So it's invalid to apply padding to a <table>. Instead, the only solution that comes to mind is to apply margin instead, wrap the table in a <div>, or apply the padding to the individual <td>s with special classes.
Take a look at the last line in his css:
table {
border-collapse: collapse;
border-spacing: 0;
}
Try removing that and seeing what happens, table cells don't often act like block level elements. I think the real problem here is that you shouldn't style the table element like this, becasue it's display property by default is table which is not the same as the box model.
Try putting padding on the cells themselves or add a margin to the table.
Works fine for me. Did you declare a DocType?
You have to apply the style to the TD's not the table.
table.home_right_top td