targeting more than one following element with element+element - css

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/

Related

add different styles when text wraps to next line

I have a div with a small heading - just two words.
When I resize da browser the text wraps and the last word goes to the next line.
I want to display different styles to the last word only when it goes to the next line. For instance: font-weight:normal instead of being bold.
Is that possible only with css?
You could use the::first-line pseudo element for this.
From MDN:
The ::first-line CSS pseudo-element applies styles to the first line
of a block-level element. Note that the length of the first line
depends on many factors, including the width of the element, the width
of the document, and the font size of the text.
section {
width: 10%;
border: 2px solid tomato;
}
h2 {
font-weight: normal;
}
h2:first-line {
font-weight: bold;
color: green;
}
<section>
<h2>Some heading</h2>
</section>
Codepen demo (resize to see the effect)
Since your content is more dynamic, you may need to use Javascript to accomplish this. An event listener on page resize that checks the height of your heading div and adjusts a span containing the second word should do the trick.
window.onresize = function(){
document.getElementById('last_word').style.font-weight = 'normal';
};
If your page content is fairly static, you could probably get away with using a css media query. I don't know of any way to have css grab the second word in a div, but if you put the second word in a span you could do something like this:
#media (max-width: 700px) {
#header_id>span {
font-weight: normal;
}
}
Of course, replacing the 700px with whatever width you find triggers the content to word wrap.

Margin on a block

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.

Formatting Cell Data

I am writing a fairly (should be) simple HTML5 site that is a HTML5 table of the Periodic Table of elements. I am trying to format the data of each cell (each element) to show the abbreviation of the element, the atomic number and the atomic weight. I wrote a few CSS classes to format these cells in the table but it renders each piece of information on a new line in the cell. How can I get the data all on the same line so it fits the site of the cell?
These are the CSS classes:
/* class for element abbreviation */
h2
{
text-align:center;
font-size:12px;
}
h6.anum
{
text-align:left;
vertical-align:top;
font-size:8px;
}
h6.aweight
{
text-align:right;
vertical-align:top;
font-size:8px;
}
And this is the relevant entry in the HTML5 code:
<td><h6 class="anum">1</h6><h2>H</h2><h6 class="aweight">1.01<h6></td>
This displays more or less like this in the cell:
1
H
1.01
I would like text to be on the same line with the 1 and 1.01 in the left and right corner respectively.
I will admit this is probably done incredibly poorly from a design standpoint but this is my first HTML class so... I'm still learning.
h1 - h6 in HTML are block elements, meaning they usually stretch out to fill their container and have a blank line on either side of them. If you want them to sit next to each other, perhaps on the same line, you will need to set display: inline on them to coerce them to regular inline elements. You may also need to adjust the margin to make them sit more closely to one another.
Example CSS:
h1 {
display: inline;
margin: 0.25em auto;
/* More styles */
}
However, this isn't necessarily the way I would do it. Personally, I would put these in a div with position: relative and then absolutely position the h6 elements the way I want them. See example Fiddle

How do you indent *every* line of a <span> element?

I have the following HTML chunk:
<span class='instruction_text'>
Line 1<br>
Line 2
</span>
And the CSS declaration of instruction_text is:
.instruction_text {
margin-left: 70px;
font-style: italic;
color: #555;
}
The first line has a 70px margin as expected, but the next line starts with no indent. How can I make ALL of the lines indented?
Use a block-level element. <div> is block-level by default, but adding the CSS display:block to your instruction_text class should send you in the right direction.
Using BR tags inside a SPAN element doesn't make a lot of sense as SPAN in an inline element which means it's meant to be used in the flow of a line of text or other inline elements.
You really should be using an element that is a "block" level element like DIV or P, e.g. one that is designed to contain multiple lines of text (or inline elements).
As you'll have noticed, you CAN use a BR tag inside a SPAN and it will cause a line break, however inline elements don't play well with margins/padding etc.

Where do you put your CSS Margins? [closed]

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 :)

Resources