TL;DR Is it a bad practice to change default display property in my CSS?
Issue
Recently, in our project we had to position 2 header tags so they would look like one. They had the same font size and similar styling so the only issue was how to place one next to another. We had 2 different ideas on that and it le do a discussion on whether or not is a good practice to change default display property
So, our very basic code
<div class="container">
<h1>Header:</h1>
<h2>my header</h2>
</div>
The outcome we would like to have:
Header: my header
Note:
The code needs to consists of 2 different headings because on mobile version we want to display them in in separate lines (so leaving default display: block).
Approach #1: Use display: inline
This is pretty stright forward. Block elements became inline so they are positioned in the same line. The disadvantage of this approach is that default display properties of both h1 and h2 were changed.
Approach #2: Use float
H1 can be positioned on the left using float: left property. This approach leaves the default display property intact, but will requires some hacks if the .container is not long enough to fit both headers in single line.
The question
It all leads to a simple question: Is it a bad practice to change the default display property of HTML elements? Is it breaking the standard and should be avoided if possible? Or is it our bread and butter and it does not really matter, as long as code is semantically correct (so headers are placed in h1, articles are placed in article etc...)
Answering your main question:
tl;dr is it a bad practice to change default display property in my CSS?
NO
WHY?
A: Because it is all about semantics
Elements, attributes, and attribute values in HTML are defined (by
this specification) to have certain meanings (semantics). For example,
the ol element represents an ordered list, and the lang attribute
represents the language of the content.
These definitions allow HTML processors, such as Web browsers or
search engines, to present and use documents and applications in a
wide variety of contexts that the author might not have considered.
So, in your case if you really need to have 2 headings semantically then you can change their styles, including the display property.
However If you don't need to have 2 headings semantically, but only for purely cosmetics/design (responsive code), then you are doing it incorrectly.
Look at this example:
<h1>Welcome to my page</h1>
<p>I like cars and lorries and have a big Jeep!</p>
<h2>Where I live</h2>
<p>I live in a small hut on a mountain!</p>
Because HTML conveys meaning, rather than presentation, the same page
can also be used by a small browser on a mobile phone, without any
change to the page. Instead of headings being in large letters as on
the desktop, for example, the browser on the mobile phone might use
the same size text for the whole the page, but with the headings in
bold.
This example has focused on headings, but the same principle applies
to all of the semantics in HTML.
** Emphasis in the quote above is mine **
P.S - Remember that headings h1–h6 must not be used to markup subheadings (or subtitles), unless they are supposed to be the heading for a new section or subsection.
With all this above in mind, here is a few (good) approaches:
If you're doing the two headings purely for design then:
add a span inside of the h1, using a media query either using mobile first approach (min-width) or the non-mobile approach (max-width).
PROs - easily manageable through CSS, changing only properties.
CONs - adding extra HTML markup, using media queries as well.
h1 {
/* demo only */
background: red;
margin:0
}
#media (max-width: 640px) {
span {
display: block
}
}
<div class="container">
<h1>Header:<span> my header</span></h1>
</div>
If you need to use the two headings semantically then:
use flexbox layout.
PROs - no need to add extra HTML markup or the use of media queries, being the most flexible currently in CSS (basically the cons from option above mentioned).
CONs - IE10 and below has partial or none support, Can I use flexbox ? (fallback for IE10 and below would be CSS TABLES)
.container {
display: flex;
flex-wrap: wrap;
align-items: center;
/*demo only*/
background: red;
}
h1,
h2 {
/*demo only*/
margin: 0;
}
h2 {
/*640px will be flex-basis value - can be changed as prefered */
flex: 0 640px;
}
<div class="container">
<h1>Header:</h1>
<h2>my header</h2>
</div>
Sources:
W3C specs - 3.2.1 Semantics
W3C specs - 4.12.1 Subheadings, subtitles, alternative titles and taglines
tl;dr is it a bad practice to change default display property in my CSS?
No. As expressed by W3C themselves; HTML conveys meaning, not presentation.
As an HTML author, it's your job to structure a page so that every section of the page carries the intended semantics as described by the documentation, so that software (browsers, screen readers, robots...) can correctly interpret your content.
As a CSS author, it's your job to alter the default styling of correct markup to present it the way you want to. This includes changing the default display properties just as much as changing the default color.
Any software can, however, decide that certain usage of CSS properties changes the way they interpret your page. For instance, a search engine could decide that text that has the same color as their parent's background should carry no weight for their ranking system.
In regards to subheadings, it's considered incorrect to markup a subheading with an <hX> element. What you should do is to decide on one <hX> element, wrap it in a <header> and wrap subheading-type text in <p>, <span> or similar.
The following is an example of proper subheadings, taken from the W3C documentation:
<header>
<h1>HTML 5.1 Nightly</h1>
<p>A vocabulary and associated APIs for HTML and XHTML</p>
<p>Editor's Draft 9 May 2013</p>
</header>
Note that there's a discrepancy between the W3C specification and the WHATWG specification where the latter uses the <hgroup> element for this specific purpose, while the former has deprecated it. I personally go with W3C's example, but most software will still understand hgroup, likely for many, many years to come, if you prefer the WHATWG approach. In fact, some argue that WHATWG should be followed over W3C when the specs differ.
In your particular example, however, I'm not sure why you chose to split the <h1> into two elements in the first place. If what you marked up as an <h1> is actually supposed to be a generic "label" for the heading, then it should probably be considered a subheading instead. If you need to split it for styling purposes, wrap the two parts of text in <span> as such:
<h1>
<span>Header:</span>
<span>my header</span>
</h1>
tl;dr is it a bad practice to change default display property in my CSS?
Its a good practice but choose carefully when to use it because it can cause some critical structure mistakes.
Why is it a good practice
The display property is open for changes. It makes HTML simple and generic. HTML elements come with a default display value that match the general behavior - what you would usually want. But they dont have to be kept and manipulated around to imitate another display property. Think about <div> for example. Obviously most of the times you want it to have display: block;, but display: flex; is much more suitable once in a while.
Lets look at a really common example of lists. <li> comes with the display property of list-item that breaks the lines for every new item.
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
But horizontal lists are very common too. So why there is no special element for horizontal list items? Writing a special element for every common display behavior adds complexity. Instead, the convention, as also suggested by W3C is to set the <li> display property to inline.
ul li {
display:inline;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
display: inline-block; as an alternative to float
float has been used massively in page layout for many years. The problem is that it wasnt created for this task and was originally designed to wrap text around elements. A well-known float issue is that non floated elements dont recognize floated children because they are being removed from the normal flow of the document. You also cannot centrally float an element. you are limited to left or right floats only.
display is much more suitable for layout many times. display: inline-block; tells browsers to place that element inline, but to treat it as though it were a block level element. This means that we can use inline-block instead of floats to have a series of elements side by side. It is more intuitive and eliminates floats <div class="clearfix"></div> which is an additional non semantic element in your HTML.
Floats are useful when there is a need to float an element so that other page content flows around it. But there is no need to always press them into the service of a complicated layout.
Things to avoid when changing display
When you change the display property remember:
Setting the display property of an element only changes how the element is displayed, NOT what kind of element it is.
<span> test case:
In HTML early versions <span> is considered an inline-level element and <div> is block-level. Inline-level elements cannot have block-level elements inside them. Giving the <span> a display:block; doesn't change his category. It is still an inline-level element, and still cannot have <div> inside.
HTML5 introduced content models. Each HTML element has a content model: a description of the element's expected contents. An HTML element must have contents that match the requirements described in the element's content model. <span> can contain only phrasing content. It means that still you cannot nest a <div> (flow content) inside a <span>. Giving <span> a display:block; still doesn't change it.
Avoid:
span {
display:block;
}
<span>
<div>
Still Illegal!
</div>
<span>
In conclusion, changing the default display property is certainly our bread and butter. Remember that it only changes how the element is displayed, NOT what kind of element it is and use it correctly.
Now about the original two heading issue:
With respect to the comments:
Let's assume for the sake of the question, that we need to have two
headings. Or let's forget about the headings for the time being. - by the author
And also to the comment:
This question is not about resetting the display value globally. Using
selectors to target only the specific elements is implied. The
question is what we should do with these elements once selected. - by the person who set the bounty
Two headings side by side not only to handle mobile layout changes, can be done in many ways. The original example is simple and correct so its actually a good way.
h1, h2 {
display: inline;
}
<div class="container">
<h1>Header:</h1>
<h2>my header</h2>
</div>
It follows HTML rules and doesnt require any additional hacks.
Sure changing the default behaviour is redundant and even can hit performance. As a subjective solution, would recommend to use flex (but i'm not sure about performance of it, altho you can google it), it's broadly supported, and doesn't change any element css properties, it's just a layout thing, check this out
.container {
display: flex;
justify-content: flex-start;
flex-direction: column;
align-items: baseline;
}
.container.mobile {
flex-direction: row;
}
web
<div class="container">
<h1>Header:</h1>
<h2>my header</h2>
</div>
<hr />
mobile
<div class="container mobile">
<h1>Header:</h1>
<h2>my header</h2>
</div>
Notice that h1 styles stay the same
Changing default css properties is not a good idea, and should be avoided to prevent unwanted shortcomings in your markup. Instead, you should give "id" or better "class" to all html elements you want to customize and do the styling for those.
Besides, using css like "h1", "div" etc. is the slowest way as the engine try to find all those elements in the page.
In your example, it doesnt matter to use display or float as long as you give your h1 elements a css class.
Also, using correct html elements for better semantics can be useful for things such as SEO etc.
best Practice is to group the two heading in hgroup and change the display property for mobile and other views using #media query.
<hgroup class="headingContainer">
<h1>Main title</h1>
<h2>Secondary title</h2>
</hgroup>
The HTML Element (HTML Headings Group Element) represents the
heading of a section. It defines a single title that participates in
the outline of the document as the heading of the implicit or explicit
section that it belongs to.
As hgroup defines a single title for a section ,therefore changing display property within hgroup is not bed practice.
UPDATE
It seems that I might've obscured the Plunker, since Anthony Rutledge obviously failed to see (or neglected to review) it. I have provided a screen shot with a few tips on how to use the Plunker.
PLUNKER - Embed
PLUNKER - iNFO
PLUNKER - Preview
Q & A
It all leads to a simple question: Is it a bad practice to change the default display property of HTML elements?
No, not at all. Matter of fact it's a very common practice of web developers (myself included), to alter not only properties of an element, but also attributes, and it's contents to name a few.
Is it breaking the standard and should be avoided if possible?
No, but perhaps the way one goes about doing it may break the code itself which IMO is a greater concern than standards. Standards of course plays an important role but not an essential one. If that were the case, then web browsers should comply under one common set of standards (I'm talking to you IE :P). Off the top of my head, here's things that should be avoided:
Using the table element for a layout
<table>
<tbody>
<tr>
<td><img></td>
<td><input type="button"/></td>
</tr>
...
Using inline styles
<div style="display: inline-block"></div>
Using inline event handlers
<div onclick='makeASandwich();'></div>
Or is it our bread and butter and it does not really matter, as long as code is semantically correct (so headers are placed in h1, articles are placed in article etc...)
Changing an element's display property is a very small yet fundamentally essential aspect of web developing. So yes I suppose it can be considered bread and butter, which would make semantics the parsley that's used as garnish and never eaten. Semantics is subjective, a way of thinking, it is not a standard. I believe a novice should be aware of it's importance (or at least how it's important to others), but should not be pontificating between an <article> and a <section> being semantically better than using a <main> and an <aside>. In due time, semantics will just feel right.
Approach #1: Use display: inline
I have never found a good reason to use display: inline because display: inline-block is a far better choice.
Approach #2: Use float
Floats are fragile antiques. Just like handling Grandma's bone china dinner plates, you must take certain precautions if you plan on using them. Be mindful of how to clear floats and don't throw them in the dishwasher.
Basically, if given only these 2 options, Approach #1 is a better choice, especially if using inline-block. I'd stay away from floats, they are counter-intuitive and break easily. I recall only using them once because a client wanted text wrapping around an image.
CSS & CSS/JS
Provided is a Snippet comprising of 3 demos:
Pure CSS solution utilizing display: flex.
Pure CSS solution utilizing display: table-row/table-cell.
CSS and minimal JavaScript solution utilizing display: inline-block and the classList API
Each of these demos are identical on the surface:
HTML
<section id="demo1" class="area">
<!--==Pure CSS Demo #1==-->
<!--======Flexbox=======-->
<header class="titles">
<h1>Demo 1 - </h1>
<h2>display: flex</h2>
</header>
</section>
This is the original markup with the following changes:
div.container is now header.titles
h1 text is: "Demo #n"
h2 text is: "prop:value"
section#demo#n.area is wrapped around everything.
This is a good example of semantics: Everything has meaning
You'll notice at the bottom of the viewport, are buttons. Each button corresponds to a demo.
Details on how each demo works as well as pros and cons are in the following files located in the leftside menu of the Plunker (see screenshot):
demo1.md flexbox
demo2.md disply: table
demo3.md classList
PLUNKER
These notes are not for the purpose of informing the OP of anything relevant to the question. Rather they are observations that I would like to address later on.
Further Notes
Demo 1 and demo 2 are powered by the pseudo-class :target. Clicking either one of them will trigger the click event It resembles an event because it's invoked by a click, but there's no way of controlling, or knowing the capture or bubbling phase if it actually exists. Upon further clicking of the first and second button, it will exhibit odd behavior such as: toggling of the other button then eventually becoming non-functional. I suspect the shortcomings of :target is that CSS handles events in a completely different way with little or no interaction with the user.
You should use:
$('element').css('display','');
That will set display to whatever is the default for element according to the current CSS cascade.
For example:
<span></span>
$('span').css('display','none');
$('span').css('display','');
will result in a span with display: inline.
But:
span { display: block }
<span></span>
$('span').css('display','none');
$('span').css('display','');
You can use flex box to arrange elements also, like this
<div class="container" style="display: flex;">
<h1>Header:</h1>
<h2>my header</h2>
</div>
Try to read this tutorial about flex, it is really great and easy to use
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Looking around for responsive web design and I came up with a piece of code which also exists in the Bootstrap framework.
Can someone please explain what the actual code does
#media only screen and (max-width: 768px) {
/* For mobile phones: */
[class*='col-'] {
width: 100%;
}
}
Could not find the selector in this site which has a lot of selectors as examples
[class*='col-']
is the so-called attribute selector. The basic form is e.g. this:
[type='checkbox']
which would select all elements on a page that have an attribute type that equals checkbox.
The basic form can be modified using certain prefix characters:
[class*='col-']
matches all elements which have a class in their classlist whose name contains (*=) col-.
The same exists for starts with:
[class^='col-']
and for ends with:
[class$='col-']
https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
Combined with the media query, what that full rule does is make any container element that is defined as a Bootstrap column have the full width (and no longer be a column) instead (which is usually what you want on mobile devices like smartphones).
This complex selector in css but it is simple indeed.
Infact this is so usefull.
In following example there are four divs and there is CSS selector which checking if there is any of the divs having test in their class, then it selects them and apply properties on them.
div[class*="test"] {
background: #ffff00;
}
<div class="first_test">The first div.</div>
<div class="second">The second div.</div>
<div class="test">The third div.</div>
<p class="test">This is some text.</p>
This CSS means: For screen only, for a viewport maximum width of 768px and below, for all elements with a class containing col-; set their width to 100%.
I wanted to know if there were a best practice for styling any element that in turn could be placed anywhere in a page and retain its margin.
For example:
An <h1> tag with a ruleset of margin-bottom: 2rem; and a <p> tag with a ruleset of margin-top: 2rem.
Now these elements can be used anywhere within a webpage. But we the <h1> is placed before the <p> tag we will be encountered with a spacing of 4rem, now the behavior that I'd like to have is to maintain the space of one or the other. As a reminder this is a small example, a web page may contain all sorts of html elements as well as buttons and other components. To create a ruleset for each instance and combination is super time consuming and cumbersome, is there a better way?
if you know margin collepsing so its help you understand that margin remaining between <h1> and p is only 2rem not 4rem and here a stackoverflow answerlink for your question... hope you got help form this
Most elements (such as <h1> and <p>) have in-built default vertical margins. These are the 'generally accepted' guidelines, and you shouldn't explicitly need to overwrite them. You can, however, and if you want to set your own 'generic' margins that can be used anywhere, the best approach would be to use classes. For example:
.margin-top {
margin-top: 15px;
}
Any element with this class (such as <h1 class="margin-top">) will have this rule overwrite their default. Naturally, you could apply the rule to h1 directly,
Yes, you will encounter situations where you have both a top and bottom margin sitting next to one another, but you will need to work out when this sort of behaviour is acceptable, and when it is not. One way to avoid this is to make use of adjacent sibling combinators:
h1 + p {
margin-bottom: 0;
}
Because the above rule has more specificity than the generic h1 selector, it will take priority.
Yes, it will be a pain to work out all of the possible combinations that you may encounter, and you will have to write rules for each scenario. But you can make use of the class-driven approach above in combination with adjacent sibling combinators to significantly help eliminate this problem:
.margin-top {
margin-top: 15px;
}
.margin-bottom + .margin-top {
margin-top: 0;
}
This will completely prevent any element with the class margin-top from applying its margin only if it follows a class with margin-bottom set.
Note that many other approaches exist to already, and one such approach makes use of a Lego analogy to suggest simply making use of a padding on each element that is equal to half of the gutter:
$gutter: 20px;
.element {
padding: $gutter / 2;
}
Which is illustrated in a complete proof-of-concept code example here.
I want to make a pricing table with three columns. Such as:
* Basic Package * * BEST VALUE * * Legendary 7 *
Awesomeness Awesome+ Awesome++
24/7 Chat Chat + Email 24/7 1-(800) #
etc. etc. etc.
Obviously, the "best-value" column would be highlighted or focus by some color or special decoration. But, I want my stylesheet to adapt for a different number of columns.
This is my HTML:
<div class="colx3 pricingPlan">
<div class="plan">Basic</div>
<div class="spotlight">Basic</div>
<div class="plan">Basic</div>
</div>
This CSS does not work:
.pricingPlan>div {
background:#999;
display:inline-block;
margin:0 auto;
}
.colx3>.plan, .colx3>.spotlight {
width:33%;
}
This CSS does work:
.pricingPlan>div {
background:#999;
display:inline-block;
margin:0 auto;
width:33%;
}
.colx3>.plan, .colx3>.spotlight {
/// EMPTY /////////
}
I don't want to combine the two selectors under one set of properties, but I think it should work the way I have it. How can I define the style of an element in two different ways? More importantly, how do I get the columns to resize dependent upon the number of total columns (defined in the class name colx3).
What you want to do is make columns of <div>s float in one row. So the latter CSS does work because in it the <div>s are defined with the property display:inline-block; which aligns them beside each other with a width of 33%. If you use the former CSS (the one you mentioned not working) and add float: left; after the defined width (width:33%;) in the selector .colx3>.plan, .colx3>.spotlightit will work.
Here is a fiddle
In order to resize columns depending upon the number of columns in a row, you can either use a JavaScript (not provided here) or a mere CSS approach, via setting the parent element with display: table; and the child columns with display: table-cell; might also work.
Also the .clearfix is defined so that the columns do not fall apart in case more <div>s are added to the document (just a fail-safe technique).
I have a div#content with many div.item inside it.
When using :last-child to make the last div.item with no border-bottom, it's OK.
But, as the content is dynamically appended using php and mysql results I'm using a conditional pagination table that will be appended after the last div.item which means at the bottom of the div#content. Here will be the problem as the CSS :last-child will not recognize the last div.item as the last-child.
my CSS looks like:
div#content div.item:last-child {
border-bottom: none;
}
as you can see I'm defining that the last child id such a div.item
Any suggestions please. thanks in advance.
!!!!! Please note that the problem is not in the fact that the content is dynamic but in the fact that the CSS :last-child doesn't recognize the div.item as the last child but the last element in the div#content despite telling the CSS that it's:
div#content div.item:last-child
One possibility I can think of is that you're appending elements that aren't <div>s and/or don't have the item class. Check the output of your PHP/MySQL script and see if there are any non-div.item elements beside (in DOM terms) the div.item elements.
Such elements will not match the selector:
div#content div.item:last-child
That selector finds only <div>s with item class, that are the last child of div#content.
Here's an example.
Before appending
<div id="content">
<div class="item"></div> <!-- [1] Selected -->
</div>
After appending
<div id="content">
<div class="item"></div> <!-- [2] Not selected -->
<div></div> <!-- [3] Not selected -->
</div>
What's being selected, what's not, and why?
Selected
This <div> element has the item class, and it's the last child of div#content.
It exactly matches the above selector.
Not selected
This <div> element has the item class, but is not the last child of div#content.
It doesn't exactly match the above selector; however, it can possibly match either one of these selectors:
/* Any div.item inside div#content */
div#content div.item
/* The last div.item child of its parent only */
div#content div.item:last-of-type
Not selected
Although this <div> element is the last child, it does not have the item class.
It doesn't exactly match the above selector; however, it can possibly match this:
/* Any div that happens to be the last child of its parent */
div#content div:last-child
It seems appending items dinamically does not make the layout engine re-run some CSS rules like :last-child.
I think you can re-read/reload CSS file making the rule apply. Don't know, it's a guess.
Another possibility is dinamically set the styles.
EDIT: It seems you have a CSS x Browser problem.
Check this out: http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28Cascading_Style_Sheets%29#Selectors
you could use javascript to refresh the CSS only. See here: http://paulirish.com/2008/how-to-iterate-quickly-when-debugging-css/
Another approach would be to use a library like jQuery and fire this line of script every time you add new divs. (or maybe you're using another js library, as you say that you are dynamically adding divs to the page)
$('div#content div.item:last-child').css('borderBottom','none');
you might need to reset borders before you do the above though. i.e. the previous 'last' div may still not have the border bottom. so reset all borders then fire the script to remove the border for the last one.