Reputation: 155
I have several data (say a name, an address, a telephone number, an e-mail address) in a row, because they occupy the thin footer of a webpage.
They are separated by a space-dash-space construct, like this (but centered):
Name - address - phone - mail address
On small screens, the whole page is smaller and the text wraps. I'm already making use of no-breaking spaces and word wraps to ensure that everything falls in place but the result is not satisfying.
What I get is:
Name - address -
phone - mail
What I want is:
Name - address
phone - mail
Is there any way, with CSS or JS, to dynamically hide some characters if they happen to be located at the start or at the end of a line?
If not, feel free to suggest different solutions that don't involve changing the original formatting of the text. Shall I find no solution, I will opt for:
- Name -- address -- phone -- mail -
turning into:
- Name -- address -
- phone -- mail -
or something like that.
Upvotes: 4
Views: 2303
Reputation: 41
Of course it is a bit late:) but I think the pure CSS solution may exists. Please see a code snipped below.
The point is that the list items (except the first one) have a negative margin on the left and the same positive margin on the right. As a result these margins annihilate being on the same line but provide a negative indent of second and further lines. And the container's "overflow: hidden;" hides the extra separators on the left. It is important here that the dividers have a fixed width.
ul {
list-style: none;
padding: 0;
overflow: hidden;
}
li {
display: inline;
white-space: nowrap;
margin-right: 0.66em;
margin-left: -0.66em;
}
li::before {
display: inline-block;
content: "-";
width: 0.66em;
}
li:first-child {
margin-left: 0;
}
li:first-child::before {
content: none;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
<li>Item 17</li>
<li>Item 18</li>
<li>Item 19</li>
</ul>
Upvotes: 4
Reputation: 4196
I don't think you can do this directly, but here's a trick that might work for you:
If your text is text-align: left
you can force breaks to happen just before your -
symbol and then do a visual clip (overflow: hidden
) to hide the left-most character or two of every line.
Demo: https://jsfiddle.net/h4t96hav/
So that does have the "-" symbol at the beginning of each line, but you can't see it because the inner div is shifted left two characters and the outer clips.
It would take a little fudging to get it to work with a variable-width font, but I think there's a decent margin for error (since there's a space).
Note that I set the chunks to be display: inline-block
so wraps wouldn't happen to the left of the numbers.
A similar trick could of course be used for text-align: right
but I can't think of a way to handle centered text.
Upvotes: 1
Reputation: 2429
There is no way to do this with pure CSS, unless you want to just--at certain screen sizes--set the list to stack vertically and remove the -
from the document dynamically.
With Javascript, it's possible, but the solution I came up with can be pretty expensive if used a lot on a page, or if the screen is resized a lot, as it can trigger fairly extensive repainting on complex layouts.
First off, each of those elements, like "Name", "Address", "Phone", etc., would have to be an inline-block element, and the -
character next to it would have to be an ::after
pseudo-element. Then, you could go through each of those inline-block
elements, and when you find one that has a vertical position on the page lower than the one before it, you would set [the one before its pseudo-element]
to display: none
and reset on page resize.
<div>
<ul class='tacky'>
<li>Name</li>
<li>Address</li>
<li>Email</li>
<li>Phone</li>
</ul>
</div>
Requires jQuery
handleList = function(c, e){
var last;
var lastHeight;
$("li", e).each(function(count, listItem){
var height = $(listItem).offset().top;
if(typeof last !== 'undefined'){
if(lastHeight < height){
$(last).addClass("no-tack");
}else{
$(last).removeClass("no-tack");
}
}
last = listItem;
lastHeight = height;
});
};
// jQuery event bindings for load
// and resize
$(document).ready(function(){
$(".tacky").each(handleList);
});
$(window).resize(function(){
$(".tacky").each(handleList);
});
The CSS is here so we can make the Javascript a little more lightweight.
.tacky
{
margin: 0;
padding: 0;
list-style-type: none;
}
.tacky li
{
display: inline-block;
}
// add tack as a psuedo element
.tacky li:after
{
content: "-";
margin: 0 5px;
}
.tacky li:last-of-type:after
{
content: "";
margin: 0;
}
.tacky li.no-tack:after
{
content: "";
margin: 0;
display: none;
}
For this, you'd just pick a screen size (or series of screen sizes) under which the menu doesn't have tacks anymore. This isn't quite as dynamic, but is a compromise that uses all CSS.
.tacky
{
margin: 0;
padding: 0;
list-style-type: none;
}
.tacky li
{
display: inline-block;
}
.tacky li:not(:last-of-type):after
{
content: "-";
padding: 0 5px;
}
// Media selector to hide tack characters.
//
// 768 is the max screen width this will
// be visible on.
@media (max-width: 768px){
.tacky li:after
{
display: none;
}
}
Upvotes: 1
Reputation: 8537
Maybe add a CSS class on a <span>
element between dash like this :
Name - address <span class="toHideOnMobile"> - </span> phone - mail address
Then use a CSS for small devices like this :
@media (max-width: 767px){
.toHideOnMobile { display: none; }
}
Upvotes: 2
Reputation: 87
If you know what you want it to split on. You can use the choose what goes to the next line by changing the CSS display property and use the CSS content property to add and remove your dashes based on the size of the display.
<style>
p > span {display: inline-block;}
p > span:after{ content: " -";}
p > span:last-of-type:after {content: "";}
@media (max-width: 500px){
p > span.street {display: block;}
p > span.street:after{ content: "";}
}
@media (max-width: 300px){
p > span {display: block;}
p > span:after{ content: "";}
}
</style>
<p>
<span class="street">1600 Pennsylvannia Ave.</span>
<span>Washington</span>
<span>DC</span>
<span>1-555-555-5555</span>
</p>
Here is a fiddle: https://jsfiddle.net/ae9j994j/4/
Upvotes: 1