Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
When you want to add whitespace between HTML elements (using CSS), to which element do you attach it?
I'm regularly in situations along these lines:
<body>
<h1>This is the heading</h1>
<p>This is a paragraph</p>
<h1>Here's another heading</h1>
<div>This is a footer</div>
</body>
Now, say I wanted 1em of space between each of these elements, but none above the first h1 or below the last div. To which elements would I attach it?
Obviously, there's no real technical difference between this:
h1, p { margin-bottom: 1em; }
...and this...
div { margin-top: 1em; }
p { margin-top: 1em; margin-bottom: 1em }
What I'm interested is secondary factors:
Consistency
Applicability to all situations
Ease / Simplicity
Ease of making changes
For example: in this particular scenario, I'd say that the first solution is better than the second, as it's simpler; you're only attaching a margin-bottom to two elements in a single property definition. However, I'm looking for a more general-purpose solution. Every time I do CSS work, I get the feeling that there's a good rule of thumb to apply... but I'm not sure what it is. Does anyone have a good argument?
I tend to use a bottom margin on elements when I want them to have space before the next element, and then to use a ".last" class in the css to remove the margin from the last element.
<body>
<h1>This is the heading</h1>
<p>This is a paragraph</p>
<h1>Here's another heading</h1>
<div class="last">This is a footer</div>
</body>
div { margin-bottom: 1em; }
p { margin-bottom: 1em; }
h1 { margin-bottom: 1em; }
.last {margin-bottom: 0; }
In your example though, this probably isn't that applicable, as a footer div would most likely have it's own class and specific styling.
Still the ".last" approach I used works for me when I have several identical elements one after the other (paragraphs and what-not).
Of course, I cherry-picked the technique from the "Elements" CSS framework.
Using advanced CSS 2 selectors, another solution would be possible that does not rely on a class last to introduce layout info into the HTML.
The solution uses the adjacent selectors.
Unfortunately, MSIE 6 doesn't support it yet so reluctance to use it is understandable.
h1 {
margin: 0 0 1em;
}
div, p, p + h1, div + h1 {
margin: 1em 0 0;
}
This way, the first h1 won't have a top margin while any h1 that immediately follows a paragraph or a box has a top margin.
If you want some space around an element, give it a margin. That means, in this case, don't just give the <h1> a bottom margin, but give <p> a top margin.
Remember, when two elements are vertically adjacent and they don't have a border or padding between them, their margins collapse. That means that only the larger of the two margins is considered - they don't add together. So this:
h1, p { margin: 1em; }
<h1>...</h1>
<p>...</p>
...would result in a 1em space between the heading and the paragraph.
This going to be driven partly by the specifics of what you're designing for, but there's a sort of rough heirarchy to these things in, say, a typical blog index:
You're going to have one footer on a page.
You're going to have one header per entry.
You're going to have n paragraphs per entry.
Establish whitespace for your paragraphs knowing that they're going to sometimes occur in sequence -- you need to worry about how they look as a series. From there, adjust your headers to deal with boundaries between entries. Finally, adjust your footer/body spacing to make sure the bottom of the page looks decent.
It's a thumbnail sketch. How you ultimately end up assigning your padding is entirely up to you, but if you approach it from an bottom-up perspective you'll likely see less surprises as you tweak first the most common/plentiful elements and then later the less common ones.
The point that Jim is making is the key. Margins collapse between elements, they are not additive. If what you want is to ensure that there is a 1em margin above and below paragraphs and headings and that there is a 1em margin below the header and above the footer, then your css should reflect that.
Given this markup (I've added a header and placed ids on the header/footer):
<body>
<div id="header"></div>
<h1>This is the heading</h1>
<p>This is a paragraph</p>
<h1>Here's another heading</h1>
<div id="footer">This is a footer</div>
</body>
You should use this css:
#header {
margin-bottom: 1em;
}
#footer {
margin-top: 1em;
}
h1, p {
margin: 1em 0;
}
Now the order of your elements doesn't matter. If you use two consecutive headings, or start the page with a paragraph instead of a heading it will still render the way that you indended.
I'm a relative newbie, but my own solution to the thing I think both you and I came up against (changing margins for one tag may sort out spacing in one part of a site, only to disturb a previously good spacing elsewhere?) is now to allocate an equal margin top and bottom for all tags. You might well want more space above and below an H1 than for an H3 or a p, but in general I think pages look good with equal spaces above and below any given piece of text, so this solution works well for me and meets your 'simple rule of thumb' spec too, hopefully!
This is how it should be done:
body > * {
margin-bottom: 1em;
}
body > *:last-child {
margin-bottom: 0;
}
Now you don't have to worry about what element is first and what element is last, and you don't have to always place a special class on your last element.
The only time this won't "work" is when the last child is one that is not rendered. In this situation you might consider applying margin-bottom:0; using a class on your last visible child.
I tend to agree with you that the first option is better. It's generally what I like to do. However, there is an argument to be made that you should specify a margin for each one of those elements and zero it out if you don't want to apply it since browsers all handle margins differently. The <p> (and the <h1> tag too I think) will usually have default margins given by the browser if none are specified.
I've just used first-child and last child. So for example in plain CSS:
h1{
margin-top:10px;
margin-bottom:10px;
}
h1:first-child{
margin-top:0px;
}
p{
margin:10px;
}
p:first-child{
margin-top:0px;
}
p:last-child{
margin-bottom:0px;
}
This is a basic example, but you can apply this to more elements and structure is nicer if using SASS, LESS etc :)
Related
I have an h3 tag which hold text inside of it that doesn't align correctly with the content below it. It can't be margin or padding because it is the h3 itself which contains the extra space to the left of it. I have use position relative to align it with the content below it ,but I want to understand what the problem is.Thanks in advance!
HTML:
<div class="details_section">
<h3>Details</h3>
<p class="bold">Name:</p>
<p>Kaleb Meeks</p>
<p class="bold">Age:</p>
<p>19</p>
<p class="bold">Location:</p>
<p>Mississippi,United States</p>
</div>
CSS:
.details_section {
width:100%;
height: 100%;
padding-left:5%;
margin-top:7%;
}
.details_section h3 {
font-size:28px;
color:#005689;
font-weight:normal;
}
.details_section p {
display:block;
font-size:14px;
color:#000;
}
It's just the font that determines that. Change the font to Times New Roman and the margin is gone. Change the D into a T and there is no spacing anymore. In a font, each letter has some kind of bounding box and some letters have a bigger bounding box than the letter itself.
If you want to remove it, (I would definitely not recommend that, since it is made like this because of the good lookings), you can do it by applying a negative margin-left to the tag. But keep in mind that this can change from device to device and especially between various starting letters. So just don't do it ;-)
See the work around in action here: http://jsbin.com/jexijonuru/edit?html,css,output
Including a reason why it is not a good idea.
You could nudge this with position:relative; right:2px; but that needs to work with whatever else your doing.
I have a block that can be used in two scenarios:
list of such blocks
individual block placed among others of different kind
What are the best practices for deciding its margin?
Say the block has class main and a precending and a following block are respectively classed preceding and following for the second scenario.
If I set a margin for main and for the second scenario, I need preceding and following to be touching main, then should I set negative margin's on preceding and following?
Or another solution is to set margins using immediate sibling selector .main+.main and not for .main.
I'm guessing I'm missing some other solutions. May I know what are other possible solutions. Also, what are the best practices here?
One way around this is to determine the margin to be set on your .main class div by chaining it to another class that you add based on circumstance. This way, you can keep all of the shared features for your main div in one place and just differentiate on the margin (or any other style that needs to be different).
DIV Individual
<div class="main individual">
DIV With others
<div class="main shared">
CSS
.main {
width:50px;
height:50px;
}
.main.individual {
margin: 5px;
}
.main.shared {
margin:1px;
}
I normally only set bottom margin to the blocks, to avoid the margin collapsing. i.e.
.element {
margin-bottom: 30px; /* or margin: 0 0 30px; */
}
I also suggest to set each class per block, and use a shared class if necessary. i.e.
<div class="element element-1">...</div>
<div class="element element-2">...</div>
You can easily use .element for shared styles, use .element-1 and .element-2 for anything that is different.
How to reduce the gap between two video tag, I have tried with margin and padding its not worked any help are appreciated
DEMO
My HTML
<div class="videoTest">
<video controls="controls"></video>
<video controls="controls"></video>
<video controls="controls"></video>
<video controls="controls"></video>
</div>
My CSS
.videoTest > video{
border:1px solid red;
margin:0;
padding:0;
}
The <video> element is an inline element by default. That's why there are gaps between them representing the whitespaces and/or line-breaks in your markup.
.videoTest > video {
display: inline-block;
border:1px solid red;
margin:0;
padding:0;
}
.videoTest {
font-size: 0;
}
By using font-size: 0, the line-breaks and whitespaces are being kind of ignored and you get rid of the gaps. Their size is set to 0.
Updated Fiddle
This is a common workaround when working with inline-blocks and is in some situations superior to floats when it comes to centering for example.
try this
http://jsfiddle.net/Ng6XU/5/
.videoTest > video{
border:1px solid red;
margin:0px;
padding:0;
float:left;
}
TRY THIS CSS :
.videoTest > video{
border:1px solid red;
margin:0;
padding:0;
float:left;
}
I have found the link which gives various method to solve this issue, may be helpful to some one Reference : http://css-tricks.com
Published April 21, 2012 by Chris Coyier
Here's the deal: a series of inline-block elements formatted like you normally format HTML will have spaces in between them.
In other words:
<nav>
One
Two
Three
</nav>
nav a {
display: inline-block;
padding: 5px;
background: red;
}
Will result in:
Often highly undesirable (check the link for the output)
We often want the elements to butt up against each other. In the case of navigation, that means it avoids the awkward little unclickable gaps.
This isn't a "bug" (I don't think). It's just the way setting elements on a line works. You want spaces between words that you type to be spaces right? The spaces between these blocks are just like spaces between words. That's not to say the spec couldn't be updated to say that spaces between inline-block elements should be nothing, but I'm fairly certain that is a huge can of worms that is unlikely to ever happen.
Here's some ways to fight the gap and get inline-block elements sitting directly next to each other.
Remove the spaces
The reason you get the spaces is because, well, you have spaces between the elements (a line break and a few tabs counts as a space, just to be clear). Minimized HTML will solve this problem, or one of these tricks:
<ul>
<li>
one</li><li>
two</li><li>
three</li>
</ul>
or
<ul>
<li>one</li
><li>two</li
><li>three</li>
</ul>
or with comments...
<ul>
<li>one</li><!--
--><li>two</li><!--
--><li>three</li>
</ul>
They're all pretty funky, but it does the trick.
Negative margin
You can scoot the elements back into place with negative 4px of margin (may need to be adjusted based on font size of parent). Apparently this is problematic in older IE (6 & 7), but if you don't care about those browsers at least you can keep the code formatting clean.
nav a {
display: inline-block;
margin-right: -4px;
}
Skip the closing tag
HTML5 doesn't care anyway. Although you gotta admit, it feels weird.
<ul>
<li>one
<li>two
<li>three
</ul>
Set the font size to zero
A space that has zero font-size is... zero width.
nav {
font-size: 0;
}
nav a {
font-size: 16px;
}
Matt Stow reports that the font-size: 0; technique has some problems on Android. Quote: "Pre-Jellybean does not remove the space at all, and Jellybean has a bug whereby the last element randomly has a tiny bit of space." See research.
Also note, if you're sizing fonts in ems, this zero font size thing can be an issue, since ems cascade the children would also have zero font size. Rems would be of help here, otherwise any other non-cascading font-size to bump it back up.
Another weirdness! Doug Stewart showed me that if you use #font-face with this technique, the fonts will lose anti-aliasing in Safari 5.0.x. (test case) (screenshot).
Just float them instead
Maybe they don't need to be inline-block at all, maybe they can just be floated one way or another. That allows you to set their width and height and padding and stuff. You just can't center them like you can by text-align: center; the parent of inline-block elements. Well... you kinda can but it's weird.
Just use flexbox instead
If the browser support is acceptable to you and what you need out of inline-block is centering, you could use flexbox. They aren't exactly interchangeable layout models or anything, but you might get what you need out of it.
Since the video tag defaults as an inline-block element, simply make the video tag a block element in CSS. Bob's your uncle.
video {display: block;}
In my case, I was using 640x480 for the video size. I changed it to 640x360 and that removed the white space above the video.
I would say that in my case setting this css helped:
height:auto;
What I want to do is target more than one <p> with the following code:
h1+p
{
margin-left: 20px;
}
h2+p
{
margin-left: 27px;
}
h3+p
{
margin-left: 35px;
}
Below is the effect I am trying to achieve:
The problem is that when there is a new <p> element, the block of text is obviously going to revert to it's normal position, without the margin, and not longer inline with the heading.
(like so)
Is there a better way of attacking this problem? (or one that works for that matter)
You can somewhat achieve this by using the general sibling selector ~ instead of the adjacent sibling selector +:
h1~p
{
margin-left: 20px;
}
h2~p
{
margin-left: 27px;
}
h3~p
{
margin-left: 35px;
}
Be careful with this, though, especially if your h1, h2, h3 and p elements all share the same parent. Due to the way that styles cascade as well as how sibling selectors work, all your p elements that follow the last h3 element will get the 35-pixel margin, even if the last heading in your container is an h1 or h2.
For instance, if you have this Markdown:
# Heading 1
Paragraph
Paragraph
## Heading 2
Paragraph
Paragraph
### Heading 3
Paragraph
Paragraph
## Heading 2
Paragraph
Paragraph
The last four paragraphs will have a 35-pixel margin, including the two that follow your last h2, because your h3~p rule is the last in the cascading order and all your elements share the same parent. This may or may not be the effect you're trying to achieve (I'm guessing it's not).
There isn't a pure CSS workaround for this, I'm afraid; you're going to have to post-process the rendered markup with JavaScript to add classes and such to your paragraphs based on your headings.
is this what you are trying to achieve? http://jsfiddle.net/chrismackie/5DgNH/
I'm trying to stray away from using tables to form the layout of my content, and I can think of two alternatives that I'd like to better learn: (1) styling list items to be side-by-side, and (2) using div blocks that float onto the same line. Both of these would have their own uses for what I'm working on.
I'm already using div tags to form the entire layout of my three-column template, but what I need to do now is a bit different. In case it helps, my project can be found here.
In short, here's my question; how would I style a div so that the width of it is 50% of the width of the area it occupies, rather than 50% of the width of the page?
As for my other question, what would be the best approach to styling list items so that they are side-by-side? I'm working on a registration script now, and instead of using a table with "Username" on the left and the input text on the right, I can use two list items.
It's late and I've been working on this project of mine for about 8 hours straight now, so I apologize if I'm asking anything confusing. Feel free to ask me any questions about what I'm trying to do.
Thanks, friends. :)
When you use percentage units for widths and heights, it is relative to the first ancestor element which has defined a width or height. Therefore, all you need to do is set up a div which is as wide as two columns:
<div class="columnContainer">
<div class="column">
Column 1
</div>
<div class="column">
Column 2
</div>
</div>
.columnContainer {
width: 800px;
}
.column {
float: left;
width: 50%;
}
There's a lot more fiddling about required than just the code above, but that's the basics. As Gabriel said, you might get a lot of value out of using a CSS framework like 960.gs
ok, so to help you out best I am going to point you to http://960.gs this is a great tool for prototyping this sort of scenario and getting solid reliable code. On to your actual issue, you probably want to set:
width: 50%;
float: left;
display: block;
on the elements you want split. Good luck.
For the width, any relative sizing is relative to the parent, so put it as a child inside the element you want to be half of. For the list items... use display: inline; or float: left;
Inline list are simple but have some drawbacks, you cant set height or width for example.
ul li {
display:inline;
}
If you need block elements you need to float list items and floats can be tedious sometimes, for example you need to take care of clearing [uod]l element.
ul {
overflow:hidden;
}
ul li {
float:left;
display:block;
}
You probably want to remove margins and paddings on list itself in both cases.
ul {
margin:0;
padding:0;
}