CSS: "AND" and + operator? - css

I want to put a space after all the headers using CSS. Like this:
if h1 = add a space after
else if h1 + h2 = add a space after also but no space in between
This is my HTML code
<article>
<h1>Title 1</h1>
...
</article>
<article>
<h1>Title 1</h1>
<h2>Title 2</h2>
...
</article>
For the CSS
h1, h2 { padding-bottom: 20px; }
The problem is, there is a space also between h1 and h2. I tried this code below but only those articles with h1 and h2 have a space after.
h1 + h2 { padding-bottom: 20px;}
Is there a way to do this? Or I should just use the h1 + h2 in CSS and add < br > for h1 only?

There's a few ways to do this, none pretty.
/* #1 */
h1 + *:not(h2),
h2 + *:not(h3) { /* etc */
padding-top: 20px;
}
/* #2 */
h1, h2 {
padding-bottom: 20px;
}
h1 + h2 {
margin-top: -20px;
}
(and variations of these.)
The problem is there is currently no way to select "backward," i.e. apply styles to an element based on what appears after it. There is only the ability to select "forward," using the + or ~ sibling combinators. So you can't override the style on an <h1> based on the existence of a subsequent <h2>.
In the CSS4 selectors draft, there is a method of specifying the subject of the selector, using the $ sign. In that case the code would look like:
h1, h2 {
padding-bottom: 20px;
}
$h1 + h2 {
padding-bottom: 0;
}
/* or even */
h1:not($h1 + h2), h2 {
padding-bottom: 20px;
}
This isn't currently available in any browsers, however.

Is there no way to know when generating the HTML if the h2 is following the h1? That seems like the best way to handle this. Then you can make a simple css rule for h2.follows_h1 { margin-top: -5px } or whatever fits exactly what you need.

Related

Avoid CSS styling between certain adjacent elements and classes

I would like to add padding-top: 20px; between h3 and body but not if h3 is preceded by another element (e.g., h2). Is this possible?
Adding padding-top to all headings gives the desired padding when a heading is preceded by body text but an undesired padding between headlines:
Note that this document is Rmarkdown created using knitr, so I don't have full control over all the html. A pure CSS-solution would be preferred.
UPDATE:
To anyone also using knitr for Rmarkdown, the solution turned out to be a rather complex targeting:
/* First h2 following h1 */
.level1 > .level2:nth-child(3) > h2 {
padding-top: 0px;
}
/* First h3 following h2 */
.level2 > .level3:nth-child(3) > h3 {
padding-top: 0px;
}
Looking at the generated HTML, I learned that the first h2 after a h1 was in the third element in level1 and that that element was called level2. Similarly for the first h3. This is what is targeted above. The structure is probably different in other documents so take a look yourself.
How about
body > h3:first-child {
padding-top: 20px;
}
That will affect only immediate child of body with a header3, with nothing in between.
Thanks to #Oram, for pointing out missing :first-child
You can use the > selector plus :first-child to target only a direct h3 child.
* {
margin: 0;
padding: 0;
}
.test {
background-color: #cccccc;
margin: 10px;
padding: 10px;
}
.test > h3:first-child { color: red; }
<div class="test">
<h3>Targeted h3</h3>
<p>Paragraph</p>
<h3>h3 not targeted</h3>
</div>
<div class="test">
<p>Paragraph</p>
<h3>h3 not targeted because of the p tag</h3>
<h3>h3 not targeted</h3>
</div>
Try this:
body > h3:first-child {
padding-top: 20px;
}
It will only apply the CSS to the first direct child of the body which is a h3.

How to get rid of margin property in media query

I've been trying to get rid of the top & right margin from this title. I have tried margin:0 & margin: none
and it hasn't worked. Any suggestions would be appreciated.
p.title {
font-family: 'Germania One';
font-style: normal;
color: #FFF;
font-size: 150px;
Position:absolute;
width:100%;
z-index:1000;
text-align:left;
margin-top: 300px;
margin-bottom: 0px;
margin-left:200px;
}
#media (min-width:320px) and (max-width:425px) {
p .title{
position:none; margin: 0 ;
}
The selector in your media query cannot override the selector preceding the media query because they are not the same. Change the selector inside your media query from p .title to p.title and it will work.
The (space combinator) in a CSS selector means the second part of the selector is a descendant of the first part, while chaining selectors without space it means the selector applies to the same element.
Therefore p.title selects any <p> tag with the class title, while p .title selects any element with the class title that is a descendant of a <p> element.
Here's the list of CSS combinators.
You made a typo:
#media (min-width:320px) and (max-width:425px) {
p.title{ /* No Space */
position:none; margin: 0 ;
}
}
You wrote p .title (with a space) instead of p.title inside the media query.
//Remove the space from p .title{} and put the media query like that-
#media (min-width:320px) and (max-width:425px) {
p.title{
position:none;
margin-top: 0;
margin-right: 0;
}
}

Simple CSS but not working

I have an H1 inside an article element.
My h1 is styled something like this:
h1 {
&:extend(.display1);
border-bottom:solid 0.1rem #divider;
color:#primaryText;
margin-bottom:2.4rem;
padding-bottom:0.7rem;
}
However, I only want to apply this styling when the H1 isn't inside an article. I thought it would be a simple addition to the CSS like this:
*:not(article) h1 {
}
However, this doesn't seem to work for me and I've been left scratching my head. Is it possible? Have I got the syntax right? Is there something else lurking in the CSS?
Any help appreciated.
Yes, you can use this:
h1 {
color:blue;
margin-bottom:2.4rem;
padding-bottom:0.7rem;
}
:not(article) > h1{
color: green
}
http://codepen.io/anon/pen/zvKKqE?editors=110
Have you tried the 'old fashioned way'?
.article h1{ /* insert styling for h1 inside article */ }
h1 { /* insert styling for h1 outside article */}
Please note that .article h1 takes all elements from h1. So make sure you override the different styles (e.g. with !important).
--EDIT--
If you want to use :not() I can't see something wrong with your lines of code.
How does the HTML looks like? I got this example in JSFiddle:
https://jsfiddle.net/2aruu0Lr/1/
It doesn't work if there is no parent tag for h1, it does if there is one like a <span> or in my case a <strong>
Hope this helps you!
Solution:
body *:not(article) h1
Does this the trick for you?
#primaryText: #000000;
#divider: lime;
.display1 {
padding: 15px;
}
h1 {
&:extend(.display1);
:not(article) > & {
border-bottom:solid 0.1rem #divider;
color:#primaryText;
margin-bottom:2.4rem;
padding-bottom:0.7rem;
}
}
Output:
.display1,
h1 {
padding: 15px;
}
:not(article) > h1 {
border-bottom: solid 0.1rem lime;
color: #000000;
margin-bottom: 2.4rem;
padding-bottom: 0.7rem;
}

CSS - successive indenting of siblings after headings

I am needing to indent all elements after headings to give a visual structured layout.
I have seen that this is possible in the this question :
Indent all tags following h2 until next h2 is hit using CSS
However, I am unable to "reset" when going back a level.
To be more clear, I need to have progressive indents which cancel when moving back.
So
H1
H2
.....
H2
.....
H3
....
H2
.....
H1
....
If possible, I would prefer to not use enclosing DIV's but rather pure CSS.
Is this possible ?
Here is a code snippet for indenting. I hope I understand what you want correctly.
* {
margin: 0;
}
h1 ~ *:not(h1) {
margin-left: 1em;
}
h2 ~ *:not(h1):not(h2) {
margin-left: 2em;
}
h3 ~ *:not(h1):not(h2):not(.h2):not(h3) {
margin-left: 3em;
}
h4 ~ *:not(h1):not(h2):not(.h2):not(h3):not(.h3):not(h4) {
margin-left: 4em;
}
<h1>H1</h1>
<h2>H2</h2>
<h2>H2</h2>
<p class="h2">test</p>
<h3>H3</h3>
<p class="h3">test</p>
<h4>H4</h4>
<p class="h4">test</p>
<h2>H2</h2>
<p class="h2">test</p>
<h1>H1</h1>
<h2>H2</h2>
<h2>H2</h2>
<h1>H1</h1>
UPD:
Oh, I see about other elements - sorry didn't get it. Maybe somehow like this?
You can use the CSS text-indent property.
h2, h2 + * {
text-indent: 50px;
}
h3, h3 + * {
text-indent: 100px;
}
Ok, here is the solution which works for me :
h1 + *:not(h1)
{
margin-left: 0em;
}
h2 + *:not(h2), h2
{
margin-left: 20px;
}
h3 + *:not(h3), h3
{
margin-left: 40px;
}
The key is to use the plus sign (+) as opposed to the tilde sign (~).
Hope this helps others also.
Edit : Ok, spoke too soon. This will successfully indent and outdent, but only for the first sibling element. If there are multiple sibling elements, it will fail.
Any ideas ?

CSS: Adjacent sibling inside a class

Trying to add a top-margin to an adjacent sibling.
<div class="container">
<h2>Header 1</h2>
<p>Some text and sentences...</p>
<h2>Header 2</h2>
<p>Some more text and sentences..</p>
</div>
Normally I would accomplish top-margin on "Header 2" by using css on the adjacent siblings.
p + h2{
margin-top: 12px;
}
However, h2 has margin defined via
.container h2{
margin: 24px 0px;
}
How can I make the adjacent siblings css work while overriding the .container h2 css?
Try the following:
.container > p + h2{
margin: 12px;
}
That is:
Select h2 elements...
...which immediately follow a p element...
...which is a child of an element with class container.
Since .container > p + h2 contains 1 class and 2 elements, it will override .container h2, which only has 1 class and 1 element.
This should work
.container p + h2 {
margin-top: 12px;
}
.container h2 is more specific than p + h2 so it is taken into consideration. You need a more specific selector to override the margin.
This should be "more specific" and override:
.container p + h2 {
margin-top: 12px;
}

Resources