I would like to select elements between h1 tags. For example, I would like to apply a style to all p between the h1#bap and the next h1, while not changing the style at any other places.
No other tags should be added (otherwise, it'd be too easy :) ).
Can't use any nth-sibiling as elements between headers can be trillions.
Obviously, I may want to apply style between other headers as well (between specific h2,...).
<h1 id="bap">bap</h1>
<p>foo bap</p>
<p>foo bap 1</p>
<p>foo bap 2</p>
<p>foo bap 3</p>
<p>foo bap 4</p>
<div>defoo bap</div>
<h1 id="random-bor">random bor</h1>
<p>balibom</>p
You can use a lesser know selector formally called the Sibling combinator (well, I think that's it's name anyway!)
Using this syntax, you can select all p elements after <h1 id="bap">bap</h1>:
#bap ~ p { color: red; }
Unfortunately, this selects all paragraph elements after <h1 id="random-bor">random bor</h1>
too, but this can be overcome by resetting the styles of those paragraph elements like such:
#random-bor ~ p { color: black; }
See this fiddle
This works in every modern browser, unfortunately it doesn't work in IE6, if that's an issue then a jQuery solution would probably be best.
h1#bap + p{color:red}
This works for the first p tag. Need to find the way to apply for all the tags. This is what I got for now
I was going to suggest to add some <div>s around each section, until I read the bit where you said no other tags should be added.
You can't do it with css alone, but you could use some JavaScript to implement this algorithm:
Loop through all the elements of the page.
When you see a <h1>, remember it's id.
For every <p>, give it a class that corresponds to the last <h1>'s id.
You should end up with something like this, which you should be able to style easily with css.
<h1 id="bap">bap</h1>
<p class="bap">foo bap</p>
<p class="bap">foo bap 1</p>
<p class="bap">foo bap 2</p>
<p class="bap">foo bap 3</p>
<p class="bap">foo bap 4</p>
<div>defoo bap</div>
<h1 id="random-bor">random bor</h1>
<p class="random-bor">balibom</>p
Then you can style things like this:
p.bap {}
p.random-bor {}
Can only be done with javascript, if you're using jquery it would look like
$('h1#bap').nextUntil("h1#random-bor",'p').css('background','red');
Edit:
How to select all content between two tags in jQuery
this explains exactly what you would like to have done
Edit2:
there is also a jquery function
http://api.jquery.com/nextUntil/
Related
I have the following code
<p>Test
<sup>1</sup>
<sup>, 2</sup>
</p>
Which are displayed like 1 , 2. When I try apply some style I don't know where, since no margins or paddings are set. So, which style should I apply for all but the first sup?
You can try just using one sup. If you need two, you can also try applying a negative margin on sup. Since you don't need it on the first-child but need it on all other children, use this:
p > sup:not(:first-child) {}
See it working here:
p>sup:not(:first-child) {
margin-left: -4px;
}
<p>Test
<sup>1,2,</sup>
<sup>3</sup>
</p>
<p>Test
<sup>1,</sup>
<sup>2,</sup>
<sup>3,</sup>
<sup>4</sup>
</p>
<p>Test
<sup>1,</sup>
<sup>2,</sup>
<sup>3,</sup>
<sup>4,</sup>
<sup>5,</sup>
<sup>6,</sup>
<sup>7,</sup>
<sup>8</sup>
</p>
Does this solve your problem ?
<p>
<sup>1, 2</sup>
</p>
If you have to use two elements, then try
<p>test
<sup>1</sup>
<sup style="margin:0; margin-left:-5; padding:0;">, 2</sup>
</p>
I hope I could help you, otherwise I'll need some more info.
Just place the comma inside the first <sup> element rather than in the subsequent ones like so:
<p>Test
<sup>1,</sup>
<sup> 2</sup>
</p>
A popular online forum that I post to does not have the ability to create inline code spans in posts. Therefore, I'm creating a userscript in Tampermonkey to turn code blocks into inline code spans unless they're immediately following a line break <br>. I've made a Tampermonkey script so far that injects a style into the <head> of the online forum, using the following selector:
br + code {
background-color: yellow;
}
<body>
<h2>Example A (this is correct)</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
<code>But after a line break, the code is yellow!</code>
</p>
<h2>Example B (unwanted behaviour)</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
After a line break, there is more text...
<code>...but the code is still yellow!</code>
</p>
<h2>Example C</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
After a line break, there is more text and an empty span <span></span>...
<code>and that makes the code not yellow anymore!</code>
</p>
</body>
Example A works perfectly, selecting only the code span that immediately follows the line break. However, example B has unwanted behvaiour.
The problem with example B is that there is plaintext content in between the line break <br> and the inline code span. It seems like the CSS selector is selecting the code span after the line break even if there is plain text content in between them and making it yellow, but I don't want that.
Example C is an HTML way of fixing this issue. I added an empty <span> in between the <br> and the <code>. This caused the CSS style not to select the code, deciding that the code was not the first element to follow the <br>.
But I would prefer a CSS-side fix to this issue. What is it, if any?
Unfortunately, because of this forum having strict policies on what tags are allowed in forum posts, any alternate methods won't work. I need an answer that actually solves the posed qustion, and I can't change the HTML provided in any way, otherwise it's likely to get stripped from my forum post. The following is a list of what I have tried. In all of the following cases the additional info will be stripped:
Attempting to put CSS classes on the parts I want to style.
Attempting to add attributes other than font-size to a section of text.
The only reason that the empty span solution (example C) works for me is that the forum server lets you set font sizes with <span style="font-size: 12px">. If I were to go through with what I have now, I would need to surround part of the line before the inline code span with this.
This isn't a CSS issue, but rather a misunderstanding of the semantics and purpose of the <p> and <br> tag. Here is a great SO post talking about semantics and their importance.
TL:DR: Restructure your HTML to be semantically correct before worrying about your CSS, and use CSS classes as appropriate rather than complicating your code with sibling selectors:
.highlighted {
background-color: yellow;
}
<p>Your first paragraph</p>
<p>A second paragraph without the linebreak</p>
<code class="highlighted">... code that is highlighted ...</code>
<p>A third paragraph</p>
<code>... this code isn't highlighted ...</code>
Why you don't put all element that you need to change background to
<div style="background-color: yellow;">
<br>
<p>
</div>
Using :nth-child() selector, <code>...<\code> can inherit its background color from its parent element or can override with a custom background color. For example, it can be implemented in your given HTML as below:
br + code {
background-color: yellow;
}
h2:nth-child(3) + p code:nth-child(3) {
background-color: inherit;
}
<body>
<h2>Example A (this is correct)</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
<code>But after a line break, the code is yellow!</code>
</p>
<h2>Example B (unwanted behaviour)</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
After a line break, there is more text...
<code>...but the code is still yellow!</code>
</p>
<h2>Example C</h2>
<p>
This text is not yellow. <code>This code is not yellow.</code>
<br>
After a line break, there is more text and an empty span <span></span>...
<code>and that makes the code not yellow anymore!</code>
</p>
</body>
I am a little bit in doubt of a small thing here. I have made a wireframe, that I started to make. The line: "A catcy piece of text" has to have a background. But how do I make that background, without styling all h2 tags? As I understand it is not good practice to give a h2 tag a class?
HTML
<section class="container-fluid" id="section1">
<div class="v-center">
<h1 class="text-center">COMPANY NAME</h1>
<h2 class="text-center">Change this <b>subline</b> here</h2>
<p class="text-center">
<br>
Get Free Membership
</p>
<h2 class="text-center">A CATCY PEICE OF TEXT</h2>
<p class="text-center"><i>Enter your email for more news</i></p>
</div>
</section>
Using an ID or even a unique class is fine, nothing wrong with it. But to answer your question without referring to the classes, you need to use the hierarchy of your DOM elements. One such way would be:
section > div > p + h2 {...}
The says select the h2 element that is the adjacent sibling of a paragraph that is the child of a div that is the child of a section.
Check out the MDN section on CSS combinators for more info.
I just started out using BEM and SMACCS for my stylesheets but have run into some trouble as far as naming deeply nested elements in the DOM. Say for instance I have a div called .main-container. Nested inside the first level of the main-container is an additional div which by convention would be named .main-container__article.
<div class="main-container>
<div class="main-container__article></div>
</div>
This is where things get confusing. Inside that article div let's say I have a header followed by a paragraph that has a nested span tags. Do I continue prepending classes with main-container__article as so?
<div class="main-container>
<div class="main-container__article>
<h1 class="main-container__article__header">Heading</h1>
<p class="main-container__article__copy">
<span class="main-container__article__copy__intro-text>Example text.</span>
</p>
</div>
</div>
How far down does the rabbit hole go when it comes to naming parent/child elements? Is there a point where you reset at the second-level element and go from there?
<div class="main-container>
<div class="article>
<h1 class="article__header">Heading</h1>
<p class="article__text">
<span class="article__text__intro-text>This is example text.</span> for a paragraph
</p>
</div>
</div>
BEM naming shouldn't resemble DOM structure because otherwise you won't be able to change markup without changes in CSS.
So for your example I'd make it like this:
<div class="main-container">
<div class="article">
<h1 class="article__header">Heading</h1>
<p class="article__copy">
<span class="article__intro-text">Example text.</span>
</p>
</div>
</div>
There's also a quite powerful thing called mixes, which gives possibility to mix different BEM entities on the same DOM node:
Heading
Example text.
So now you may apply CSS to article block and main-container__article element separately which is very useful when you need to reuse article outside main-container.
.main-container__article__copy__intro-text
definitely doesn't help the readability and maintainability of your stylesheets.
I suggest to break such giant blocks into several smaller blocks. If you do this, you can reuse your styles - in your example you couldn't use the article-block somewhere else.
I would "reset" everytime you can encapsulate a block which can potentially be used in several places in your app/website.
Looking at the CSS3 specs, I can't find any way to select any element that has no children.
Let me explain.
<body>
<h1>Main Page</h1>
<div id="main">
<div class="post">
<h2>Article 1</h1>
<p>some text</p>
</div>
<div class="post">
<h2>Article 2</h1>
<p>some text</p>
</div>
</div>
</body>
I'm looking for a CSS syntax to select the h1, the two h2 and the two p. A way to select in any page, all elements with no children.
Any suggestion ?
Sorry, I forgot to add the "empty" part, I am actually already using the *:empty selector, but it's not working for any tag that has a nodeText as a child. So it's working for any input, image, object, but not for h2, h1, or any p.
As a text node is also a node for CSS you cannot do it with any CSS selector. Doing it with JavaScript you should first select all nodes with only one child and than test if it is only a text node.
Use the :empty pseudo to do the trick, e.g. to select ALL elements with no children (including no text nodes... nothing):
*:empty
I don't think this can be done with CSS alone. You would have to loop through all elements testing for a false return on hasChildNodes(). It would be sloppy and not something I would recommend.