Reputation: 5636
I am aware of the :first-line
selector in CSS, but I cannot find anything that will allow me to select the last line.
The reason I am trying to select the last line is because I want to be able to define the text-overflow
and white-space
attributes of the last line.
I am trying to avoid using JavaScript to form a solution.
Upvotes: 17
Views: 24738
Reputation: 3230
You can use getComputedStyle
to attempt to "clone" the original paragraph styles. Then set height:auto
on the clone and add words in 1 by 1 detecting wrapping based on the offsetHeight
change of the clone.
This probably doesn't work under a variety of conditions:
p { line-height:0; }
But for simple cases, it does work if you really need it. But it is definitely a hack. You can use similar technique to figure out text size to avoid wrapping when working with dynamic text length (contrived example...usually not user friendly to dynamically size text).
Pen if the below example doesn't work or if you prefer pug/scss.
// https://stackoverflow.com/a/19824266/
function copyNodeStyle(sourceElement, targetElement) {
var computedStyle = window.getComputedStyle(sourceElement);
Array.from(computedStyle).forEach(function (key) {
return targetElement.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key));
});
}
function getElementHeight(el) {
return el.offsetHeight;
}
function createTestElement(sourceElement) {
var body = document.getElementsByTagName('body')[0],
elTest = document.createElement(sourceElement.tagName);
body.appendChild(elTest);
copyNodeStyle(sourceElement, elTest);
elTest.style.height = 'auto'; // so height adjusts based on content (width should be fixed to match original)
elTest.style.transform = 'translateX(-2000px);'; // make sure test element is hidden out of viewport.
// could break things if original sizing was dependent on a transform
elTest.textContent = 'A'; // default content, single character (no wrapping possible)
return elTest;
}
function getLines(sourceElement) {
var elTest = createTestElement(sourceElement),
oneLineParagraphHeight = getElementHeight(elTest),
tokens = sourceElement.textContent.split(/ +/g),
lines = [],
line = '', token, currHeight;
for (token of tokens) {
// add the next token and check if we wrapped
elTest.textContent = line + ' ' + token;
currHeight = getElementHeight(elTest);
if (currHeight > oneLineParagraphHeight) { // adding this token caused wrap
lines.push(line);
line = token; // this token starts a new line
}
else {
line += ' '+token; // token part of current line
}
}
lines.push(line);
elTest.remove(); // remove our test element
return lines;
}
const sourceElement = document.querySelector('#demo'),
lines = getLines(sourceElement);
console.log('lines', lines);
// modify last line (so there was some point to getting lines)
lines[lines.length-1] = '<span class="last-line">'+lines[lines.length-1]+'</span>';
sourceElement.innerHTML = lines.join(' ');
p#demo {
width: 300px; /* constrain width so text wraps */
border: 1px solid red; /* so we can see bounding box */
}
p#demo .last-line {
color: purple;
font-weight: bold;
}
<p id="demo">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pellentesque lectus in pellentesque dictum. Maecenas ultrices et neque in iaculis. Maecenas accumsan leo vel dolor sollicitudin gravida.</p>
Upvotes: 1
Reputation: 5
You can use only one line and give css : nth-child(3)
Here (3) denotes the number of a last line
Upvotes: -3
Reputation: 7310
Unfortunately there is no CSS selector that would apply.
You can however select the first line using the pseudo element :first-line
. Unfortunately at the moment there is no equivalent for the last line.
Upvotes: 9
Reputation: 1163
I don't think this can be done with CSS alone. jQuery or a PHP function might be able to get want you what
Upvotes: 3
Reputation: 4084
IIRC, the only css control over the last line is text-align:
text-align-last: right;
I'm afraid javascript, or actually wrapping the last line in a span and styling that, is the only way. Below is the JS for reference.
var thetext = document.getElementById('some_element').innerHTML.split(/\r?\n/);
alert(thetext[thetext.length - 1]);
Upvotes: 4