I\'m working on the CSS for a container object. I have it mostly working. Specifically, I\'m looking at test case 1, 2 and 3. They all have text nodes. Is there a way to tre
In this case, I'd be tempted to place each text node inside a <span>
which is the classic, non-semantic phrasing element.
(See: http://www.w3.org/TR/html-markup/span.html)
You can then style the span
in a similar manner to the way you have styled the p
and the code
.
If you choose this approach, you have two choices. You can either:
1) Write the spans
directly into the markup:
code, p, quote, span {
display: block;
position: relative;
margin: 0;
padding: 1em;
border: 1px solid black;
box-sizing: border-box;
}
p {background-color: #0df;}
code {background-color: #ccc;}
span {background-color: #fff;}
.container {
display: block;
position: relative;
margin-right: 0;
margin-left: 0;
margin-top: 1.5em;
margin-bottom: 1.5em;
padding: 0.5rem;
border: 1px solid black;
box-sizing: border-box;
border-radius: 10px;
box-shadow: none;
}
.container :first-child {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-width: 0;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.container >:last-child {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border-bottom-width: 0;
border-left-width: 0;
border-right-width: 0;
margin-top: 0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.container >:not(:first-child):not(:last-child) {
margin-left: -0.5rem;
margin-right: -0.5rem;
margin-bottom: -0.5rem;
border-right-width: 0;
border-left-width: 0;
border-bottom-width: 0;
}
.container >:only-child {
border-radius: 10px;
border-width: 0;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
<div id="container-1" class="container">
<p>first child</p>
<span>text</span>
<code>last child</code>
</div>
<div id="container-2" class="container">
<p>first child</p>
<span>text</span>
</div>
<div id="container-3" class="container">
<span>text</span>
<p>last child</p>
</div>
Or, if you prefer not to have spans
included in your markup, you can
2) Add the span
elements dynamically, after the page loads:
var containers = document.getElementsByClassName('container');
for (var i = 0; i < containers.length; i++) {
for (var j = 0; j < containers[i].childNodes.length; j++) {
if (containers[i].childNodes[j].nodeName !== '#text') {continue;} /* skips all nodes which aren't text nodes */
if (/^[\s\n]*$/.test(containers[i].childNodes[j].textContent)) {continue;} /* skips all text nodes containing only whitespace and newlines */
var text = containers[i].childNodes[j];
var span = document.createElement('span');
span.appendChild(text);
span.textContent = span.textContent.trim();
containers[i].insertBefore(span,containers[i].childNodes[j]);
}
}
code, p, quote, span {
display: block;
position: relative;
margin: 0;
padding: 1em;
border: 1px solid black;
box-sizing: border-box;
}
p {background-color: #0df;}
code {background-color: #ccc;}
span {background-color: #fff;}
.container {
display: block;
position: relative;
margin-right: 0;
margin-left: 0;
margin-top: 1.5em;
margin-bottom: 1.5em;
padding: 0.5rem;
border: 1px solid black;
box-sizing: border-box;
border-radius: 10px;
box-shadow: none;
}
.container :first-child {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-width: 0;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.container >:last-child {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border-bottom-width: 0;
border-left-width: 0;
border-right-width: 0;
margin-top: 0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
.container >:not(:first-child):not(:last-child) {
margin-left: -0.5rem;
margin-right: -0.5rem;
margin-bottom: -0.5rem;
border-right-width: 0;
border-left-width: 0;
border-bottom-width: 0;
}
.container >:only-child {
border-radius: 10px;
border-width: 0;
margin-top: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
margin-right: -0.5rem;
}
<div id="container-1" class="container">
<p>first child</p>
text
<code>last child</code>
</div>
<div id="container-2" class="container">
<p>first child</p>
text
</div>
<div id="container-3" class="container">
text
<p>last child</p>
</div>
Only text that is wrapped in HTML tags can be targeted by CSS.
Your text that is not explicitly wrapped by HTML tags is algorithmically wrapped by anonymous boxes. These boxes may inherit styles, but they cannot be targeted by CSS.
From the spec:
9.2.1.1 Anonymous block boxes
The properties of anonymous boxes are inherited from the enclosing non-anonymous box. Non-inherited properties have their initial value.
If adding HTML tags around your anonymous text is not an option, consider setting the text styles on the container. For the elements that can be targeted, you can then override the container styles. Of course, this method will fall flat if you want the text to have display: none
.