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.
Related
I'm using jQuery to add a Class to a few elements.
I'm not new to adding classes, nor removing them. But I'm still somewhat intermediate with styles and any flexibility styles can perform to single elements.
Here's what's going on:
I have 2 Divs that I'm affecting with jQuery:
<div id="columnleft">stuff in here</div>
<div id="columncenter">bigger stuff in here</div>
In a nutshell, column left is about 155px wide, while columncenter is positioned relative to columnleft, with a margin-left of 162px
Here's my styles:
<style>
#columnleft {
float:left;
position:relative;
text-align:left;
width:155px;
}
#columncenter {
position:relative;
padding-bottom:50px
margin:0;
margin-left:162px;
}
</style>
I'm basically toggling these 2 divs with the jQuery examples below:
So far I've gotten these 2 separate instances to work:
$("#columnleft").hide();
$("#columncenter").css("margin","0px");
then........
$("#columnleft").show();
$("#columncenter").css("margin-left","162px");
Though this works, I'm not quite satisfied.
I'd prefer to create a class or two that I can use to toggle the hiding of columnleft, while also changing the margin-left at the same time.
It's all fine with the example above, when I'm only using jQuery. But there are times when a page loads, and the columnleft is meant to be hidden, and columncenter is meant to be expanded, from the beginning. Would be nice to not need jQuery to enter the scene at those moments.
All I could come up with is:
<style>
.disappear { display:none; }
.maximize { margin:0px; margin-left:0px; }
</style>
When the page loads:
<div id="columnleft" class="disappear">stuff in here</div>
<div id="columncenter" class="maximize">bigger stuff in here</div>
it seems that columncenter is ignored. (columnleft indeed does disappear)
Also, toggling with jquery, the same result occurs.
Column Center hates me!
Does anyone see where I'm missing the mark?
View JSFiddle: http://jsfiddle.net/tuanderful/bTZq8/
What if you had another div that contains both #columnleft and #columncenter, and has a class of .hide-left or .show-left:
<div class="hide-left">
<div id="columnleft">stuff in here</div>
<div id="columncenter">bigger stuff in here</div>
</div>
​
Then add the following CSS:
.show-left #columnleft {
display: block;
}
.show-left #columncenter {
margin-left: 162px;
}
.hide-left #columnleft {
display: none;
}
.hide-left #columncenter {
margin-left: 0;
}
You can update your jQuery to simply toggle the .hide-left or .show-left classes on the parent container.
What I did here is similar to adding .disappear and .maximize styling, but I added a bit of context around the two columns. The neat thing is that all of the styling is handled purely by CSS - when you want to show or hide your sidebar, you only need JavaScript to update the state of the container; that is, change the class in the container from hide to show or vice versa.
You need to put !important on the css styling.
.maximize {
margin-left: 0px !important;
}
That makes it so that it overrides any other styling of the same kind. Check it out here.
There is an order of importance in CSS. An id # is considered more important than a class . (there can only be one id and many classes after all). So if you are trying to override an id with a class, you need to use !important.
each type of selector in css is weighted differently id being higher than classes and classes being higher than objects
to fix your problem make the selector as such
#columncenter.maximize
this will overwrite the rule before it
don't use !important while it might work now it can be hard to find out why something is being overridden later on
I have two sibling divs sitting below each other, both contained in the same parent div.
The requirement is that the divs need a certain amount of space between them, let's say 20px, but the space beween the inner divs and the parent div needs to be the same on all sides (top, right, bottom, left), in this case 0px.
The constraint here is that the inner divs need to have the exact same markup, so I can't apply a different or additional class to just one of them. Also I can't add any markup between the child divs or only above or below one of the child divs.
What would be a good way to solve this problem with CSS (no javascript), in a cross-browser compatible way?
Thanks!
#parentdiv div {
margin-top: 20px;
}
#parentdiv div:first-child {
margin-top: 0;
}
should do it. Alternatively, you could try
#parentdiv div + div {
margin-top: 20px;
}
Which solution to use depends on browers’ support of either the :first-child pseudo-class, or the + adjacent selector. Any modern browser (thus, discounting IE6) should support both.
you could insert another div inbetween them and make its height 20px? or is putting the first inner div into a new div and then making the new divs bottom margin 20px an acceptable solution?
As others have already stated, you cannot use a pure CSS approach that will work in IE6. However, why not use a minified, basic jQuery framework - without the ui it will be tiny - and then you can call the first child and apply the margin to that:
$("#parentdiv:first").css({ marginTop: 0 })
That way you'd have already applied the margin-top:20px; in your css, now you're removing it from the first child only. I know you said you did not want a javascript approach, but you're not left with much choice, unless you're willing to re-engineer ie6 and resurrect him for us?
Hope this helps someone somewhere.
Two divs sitting below each other? Do you mean they're stacked vertically, one on top of the other? Margin-top would do it as long as you don't have padding on the parent div.
Try this example.
<html>
<head>
<style>
div.parent {
background-color: #AAA;
}
div.child {
background-color: #CCC;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"> </div>
<div class="child"> </div>
</div>
</body>
</html>
You'll notice that as long as there's nothing inside the parent above the first child its margins won't extend the parent div.
If they're side-by-side and floating that's a different story, margin-left doesn't work the same as margin-top. You might be able to use margin-right on both divs but fix the width of the parent and set overflow to hidden in order to chop off the extended margin - but I'm not sure about compatibility on that kind of thing.
Are you absolutely certain you've got no way to distinguish the two divs? Finding a way around that constraint might do a lot to help you.
I have these 3 icons enclosed in separate DIVs all of which are enclosed within a single DIV:
<div id="icons">
<div id="divtxt" class="divicon">
<img src="/icons/text.png" id="icontxt" class="icon"/>
</div>
<div id="divpdf" class="divicon">
<img src="/icons/pdf.png" id="icondoc" class="icon"/>
</div>
<div id="divrtf" class="divicon">
<img src="/icons/rtf.png" id="iconrtf" class="icon"/>
</div>
</div>
I set some simple styles but can't figure out why these images are lining up top-to-bottom instead of left-to-right:
div#icons
{
width:200px;
height: 100px;
}
div.divicon
{
margin: 0 0 0 0;
padding: 0 0 0 0;
border: 0 0 0 0;
}
Any suggestions would be appreciated.
And now for something a bit more comprehensive:
You look like you just want a row of icons. Using your HTML, you would need to float the divs containing the icons in order for them to be next to each other. The reason why you need to float is because a div is a block level element (as opposed to inline) which means that nothing can exist in the horizontal space next to it.
You can achieve this effect by adding a float: left; rule to div.divicon
Floating does two things: it takes the block element out of the page flow allowing other elements to exist next to it (or flow around it) and it reduces the width of the box to fit the content. As far as the parent is concerned, a floated element has no height. To illustrate this, just try giving #icons a background color or border. You will notice that it won't show up - or show up as a 1px line.
In order for the parent to recognise the height of the floated element you need to tell the parent that overflow should be hidden with this rule:
#icons { overflow:hidden; }
This also works in IE however not always, so sometimes you might need to set a height or width or do a zoom:1 which tends to fix a lot of IE bugs (look up "hasLayout bug" if you want more info).
Now for a different solution:
You look like you just want a row of icons. Unless theres a reason for the images to be surrounded in a div (and in your example there is none) I would suggest to you to do something like this:
<div id="icons">
<img src="/icons/text.png" id="icontxt" />
<img src="/icons/pdf.png" id="icondoc" />
<img src="/icons/rtf.png" id="iconrtf" />
</div>
#icons { /* rules for our container go here */ margin:0; padding:0; /* etc... */ }
#icons img { /* rules for your icons */ border:none; margin:0 2px; /* etc... */ }
I have removed the redundant divs and the redundant class attribute on the images. Since images are inline elements you wont need to screw around with floats and you wont have any extra divs that may cause divitis a degenerative HTML disease that affects many websites and spreads through bad advice. Remember, only use what you need - don't use it just because its there.
Hope this helps,
Darko
You need a
float: left;
in your div#icons.
div is a block level element. So the default behavior is to layout one below the other, unless you float them like Robert suggested.
I've used the last example on this page for equal height columns.
http://www.ejeliot.com/blog/61
The problem is, when you click an internal anchor link, the content is shifted up, and the overflow is making the top part of the page disappear.
For example, click this link
http://www.noosanativeplants.com.au/~new/articles/botany-words/
Then click a letter to jump to that section. You will notice what I am describing.
Is there a way to combat this, or is this a short coming of the technique? Do you recommend I use the background image technique for faux equal height columns? I'd rather not use this, as one page has a different background, and would require a bit of reworking to do the background for this page.
Thanks
I really recommend you to use the fail-safe faux columns method. If you are not a layout expert (no offence, seriously), stay away from the padding/margin/overflow magic and the one true layout technique. The latter is elegant but it can cause unwanted side-effects if you are to do heavy JS/DOM manipulations and all (see the problems listing).
As slink said you have two overflow: hidden rules in your css:
#main-container {
overflow:hidden;
}
And
#content {
overflow:hidden;
}
If you disable/remove these you will able to use your scrollbars again. Unfortunately the padding / negative margin "hack" will be visible. I recommend you to completely remove this solution and use faux columns. Faux columns background can be added to your #main-content or even the #content div (not just like the example in the ALA article that sets the background image to the body tag).
Good luck!
Update: Sorry, let me correct myself: to use faux columns in your case it is better to set the current background to the html element and the faux background to body element.
Assuming your equal height columns are the left menu and right content in that example, you could just use a margin-left property on the right-column and set the background colour of the container to the desired left-column colour. This would assume your right content always has a greater height than the left, but there are other ways round this.
#container {
width: 960px;
background-color: #000;
}
#menu {
float:left;
width: 240px;
}
#content {
float:right:
margin-left: 240px;
background-color: #fff;
}
<div id="container">
<div id="menu">
<ul>
<li>Home</li>
</ul>
</div>
<div id="content">
stuff goes here
</div>
</div>
The problem is caused by two overflow: hidden; rules defined on elements #content and #main-contaniner.
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 :)