Reputation: 145
I am creating a custom Tumblr theme, and I've hit a small problem with <blockquote>
. I am trying to show only the first <blockquote>
(which is the last blockquote
here in the code) in a <div>
. For example:
<div class="post-content">
<div class="body-text">
<p><a href="http://example.com" class="tumblr_blog">Lorem</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Ipsum</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Dolor</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Sit</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Amet</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Consectetur</a>:</p>
<blockquote>
<p>Phasellus scelerisque dui sed velit facilisis pulvinar. Cras congue quis lorem ac feugiat.</p>
</blockquote>
<p>Aenean maximus mi sollicitudin, rutrum mauris vel, laoreet magna. Proin vitae tristique nisl.</p>
</blockquote>
<p>Maecenas eu orci consectetur, hendrerit arcu at, imperdiet massa.</p>
</blockquote>
<p>Vestibulum in ornare massa. Duis felis arcu, bibendum quis nisl eget, tincidunt facilisis urna.</p>
</blockquote>
<p>Fusce lobortis laoreet rutrum. Nam in arcu quis erat laoreet consequat eget quis est.</p>
</blockquote>
<p>Maecenas vitae dui viverra, varius nisl id, tempus turpis. Mauris nec lobortis sem.</p>
</blockquote>
</div>
</div>
Targeting the very last <blockquote>
(which is the first quote shown on theme) is what I'm trying to do, but I'm not sure of the approach. The fact that the last blockquote
is nested in other blockquotes is what's causing the difficulty.
Does anyone know of a way to target this last blockquote
element?
Note: I should have mentioned this, since this is code for a Tumblr theme, the number of blockquotes will always vary, and so it can't be targeted by the amount.
Upvotes: 2
Views: 881
Reputation: 1730
Unfortunately as far as I am aware you cannot make the selection you want via pure CSS. However, it is certainly possible via Javascript and jQuery makes the job much easier.
For example, you could use a function such as this to return the deepest nested blockquotes:
function getDeepestQuotes() {
var el;
// Get the first quote on the post to iterate through
el = $('.body-text > blockquote');
// Make sure there are actually quotes
if (!el.length) {
return null;
}
// Keep going down the stack until we find the one we want
while (el.length > 0) {
el = el.children('blockquote');
}
// el is now empty - step back up the stack and grab the last working state
el = el.end();
// el now contains the lowest scoped blockquotes
return el
}
Live Example:
function getDeepestQuotes() {
var el;
// Get the first quote on the post to iterate through
el = $('.body-text > blockquote');
// Make sure there are actually quotes
if (!el.length) {
return null;
}
// Keep going down the stack until we find the one we want
while (el.length > 0) {
el = el.children('blockquote');
}
// el is now empty - step back up the stack and grab the last working state
el = el.end();
// el now contains the lowest scoped blockquotes
return el
}
var q = getDeepestQuotes();
if (q) {
q.addClass('last-quote');
}
blockquote {
border-left: 15px solid gray;
}
.last-quote {
border-left-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="post-content">
<div class="body-text">
<p><a href="http://example.com" class="tumblr_blog">Lorem</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Ipsum</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Dolor</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Sit</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Amet</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Consectetur</a>:</p>
<blockquote>
<p>Phasellus scelerisque dui sed velit facilisis pulvinar. Cras congue quis lorem ac feugiat.</p>
</blockquote>
<p>Aenean maximus mi sollicitudin, rutrum mauris vel, laoreet magna. Proin vitae tristique nisl.</p>
</blockquote>
<p>Maecenas eu orci consectetur, hendrerit arcu at, imperdiet massa.</p>
</blockquote>
<p>Vestibulum in ornare massa. Duis felis arcu, bibendum quis nisl eget, tincidunt facilisis urna.</p>
</blockquote>
<p>Fusce lobortis laoreet rutrum. Nam in arcu quis erat laoreet consequat eget quis est.</p>
</blockquote>
<p>Maecenas vitae dui viverra, varius nisl id, tempus turpis. Mauris nec lobortis sem.</p>
</blockquote>
</div>
</div>
(Note that this will return all the quotes in the first quoted post. If you only want the first quote of a split quote, replace return el
with return el.first()
. Equally, this will work iteratively on split quotes to retrieve the most nested quote. If this is a problem you will need to chuck a .first()
after each selector modification.)
The above example demonstrates jQuery's state stack - this can be useful if you wish to iterate through all the quotes to perform some form of nested styling.
As another example, here is a snippit that will render all quotes in a monochromatic rainbow with the oldest at black and the newest in light gray, no matter how deep it goes:
var el;
// Get the first quote on the post to iterate through
el = $('.body-text > blockquote');
// Make sure there are actually quotes
if (!el.length) {
return;
}
// Keep going down the stack until we find the one we want
var depth = 0;
while (el.length > 0) {
el = el.children('blockquote');
depth++;
}
// el is now empty - step back up the stack and grab the last working state
el = el.end();
// Don't cancel depth - so that the top level has at least some gray in it.
//depth--;
// el now contains the lowest scoped blockquotes
// Save the max depth for later
var maxDepth = depth;
// Step back up the jQuery stack and operate on each level of quoting
while (el.length) {
// Generate a black and white rainbow using the stack depth for blackness
var hsla = 'hsla(0, 0%, ' + (100 - Math.floor((depth / maxDepth) * 100)) + '%, 1)';
el.css('border-left-color', hsla );
// Step up
el = el.end();
depth--;
}
Live Example:
function bwRainbowQuotes() {
var el;
// Get the first quote on the post to iterate through
el = $('.body-text > blockquote');
// Make sure there are actually quotes
if (!el.length) {
return;
}
// Keep going down the stack until we find the one we want
var depth = 0;
while (el.length > 0) {
el = el.children('blockquote');
depth++;
}
// el is now empty - step back up the stack and grab the last working state
el = el.end();
// Don't cancel depth - so that the top level has at least some gray in it.
//depth--;
// el now contains the lowest scoped blockquotes
// Save the max depth for later
var maxDepth = depth;
// Step back up the jQuery stack and operate on each level of quoting
while (el.length) {
// Generate a black and white rainbow using the stack depth for blackness
var hsla = 'hsla(0, 0%, ' + (100 - Math.floor((depth / maxDepth) * 100)) + '%, 1)';
el.css('border-left-color', hsla );
// Step up
el = el.end();
depth--;
}
}
bwRainbowQuotes()
blockquote {
border-left: 15px solid gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="post-content">
<div class="body-text">
<p><a href="http://example.com" class="tumblr_blog">Lorem</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Ipsum</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Dolor</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Sit</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Amet</a>:</p>
<blockquote>
<p><a href="http://example.com" class="tumblr_blog">Consectetur</a>:</p>
<blockquote>
<p>Phasellus scelerisque dui sed velit facilisis pulvinar. Cras congue quis lorem ac feugiat.</p>
</blockquote>
<p>Aenean maximus mi sollicitudin, rutrum mauris vel, laoreet magna. Proin vitae tristique nisl.</p>
</blockquote>
<p>Maecenas eu orci consectetur, hendrerit arcu at, imperdiet massa.</p>
</blockquote>
<p>Vestibulum in ornare massa. Duis felis arcu, bibendum quis nisl eget, tincidunt facilisis urna.</p>
</blockquote>
<p>Fusce lobortis laoreet rutrum. Nam in arcu quis erat laoreet consequat eget quis est.</p>
</blockquote>
<p>Maecenas vitae dui viverra, varius nisl id, tempus turpis. Mauris nec lobortis sem.</p>
</blockquote>
</div>
</div>
This is of course all possible via normal JS & DOM queries, but jQuery uncomplicates matters.
Upvotes: 1
Reputation: 1892
Expanding on first answer:
If you know that the last blockquote is always the third blockquote you could do:
.entry blockquote blockquote blockquote { }
// ".entry>blockquote>blockquote>blockquote" would be more specific
I would suggest a class or shorter unique selector. CSS selectors are calculated from the inside out. It'll first find all blockquotes, then remove those who aren't children of blockquotes, then remove those who aren't children of blockquotes who are children of blockquotes, then finally remove those who aren't inside of the entry class. You're best off using a class for the 3rd level or something else of the sort in order to increase performance.
Upvotes: 0
Reputation: 132
If you know that the last blockquote is always the third blockquote you could do:
.entry blockquote blockquote blockquote { }
Upvotes: 0