Forum Moderators: not2easy

Message Too Old, No Replies

bullets between items, but not at the end of lines.

this one's tricky! how do I do it?

         

httpwebwitch

4:27 am on May 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



OK, I am ready to accept there may not be a way to do this. But I figure it can't hurt to throw this in front of some CSS experts...

Here is my markup:

<ul>
<li><nobr>phrase one</nobr></li>
<li><nobr>phrase two</nobr></li>
<li><nobr>phrase three</nobr></li>
<li><nobr>phrase four</nobr></li>
<li><nobr>phrase five</nobr></li>
</ul>

my DOCTYPE is strict, xhtml.

What I'm looking for is for all these phrases to be inline, centered, wrapping at phrase boundaries (not word boundaries). AND (here's the tricky part) I'd like a bullet image BETWEEN items, but not at the beginning or end of each line.

example:

one * two * three * four * five

six * seven * eight * nine * ten

eleven * twelve * thirteen

fourteen * fifteen * sixteen

See how the bullets are between the items, but don't appear at the ends of each line. Each of those bullets is actually going to be a little flower glyph.

How do I insert those bullets?

The tricky thing here is that the text is dynamic. I want it displayed in this way, but I can't predict the length of the phrases, or where they will wrap.

here's where I'm starting from:

ul{
text-align:center;
}
li{
list-style:none;
display:inline;
padding:0 10px;
}

help me CSS forum, you're my only hope

swa66

9:01 am on May 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hmm. <nobr>? That's not part of xhtml1.0 strict AFAIK (and the validator at [validator.w3.org...] seems to agree with me.)
Try the css property "white-space: nowrap" instead.

To get your bullets:
:first-child pseudo selector can be used to select the first child differently from the others.

:before can be used to create an element (e.g. having your image as background) before some elements.

As an alternative to bulletds, there's an argument to not turn of bullets, but to use "list-style-image: url(bullet.gif);", you'll have a graceful degradation to a regular bullet as well.

Even then, I see no easy way to let them wrap themselves and select the first one on a new line, so if you can wrap them yourself it would help a lot. But others might have something up their sleeve.

But getting it all supported in IE is going to be hard (esp. so for the poor excuse for a browser that IE6 is)

topr8

10:17 am on May 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



sorry, misunderstood you

pageoneresults

12:56 pm on May 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Hmmm, I've managed to get the first part down but have not been able to break at whole phrases. It will break naturally but not on a phrase.

#bottomnav ul, #bottomnav li{
margin:0;
padding:0;
list-style-type:none;
}
#bottomnav ul li{
background:url(/images/nav/bullet.gif) left center no-repeat;
margin:0;
padding:0 2px 0 12px;
display:inline;
}

<added> Oh wait, the above is still going to put a bullet at the start of each <li> (that first one).

Have you tried using &middot;

SuzyUK

6:25 pm on May 19, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



you could use separate lists for each 'phrase' as that's what they are? - that would get the break where you want it

then it would be very simple if you can use the advanced selectors, remove the bullet style from the lists, add left padding and make your "bullet" a background image, but only apply that padding and background image to

ul li+li {}
that will mean the first one in the list doesn't get a "bullet"

or if IE6 support is important it won't understand the

li+li
so you might need to give the first item in each list a class to make it different.

ul {
margin: 0;
padding: 5px 0;
list-style: none;
background: #abc;
text-align: center;
white-space: nowrap;
}

ul li {
display: inline;
background: transparent;
}

ul li+li {
padding: 0 0 0 16px; /* image width + 4px; */
background: transparent url(bullet.jpg) no-repeat 0 50%;
}

or if first item has classname.first

ul {
margin: 0;
padding: 5px 0;
list-style: none;
background: #abc;
text-align: center;
}

ul li {
display: inline;
background: transparent;
padding: 0 0 0 16px; /* image width + 4px; */
background: transparent url(bullet.jpg) no-repeat 0 50%;
}

ul li.first {
padding: 0;
background: transparent;
}

example HTML

<ul class="phrase1">
<li class="first">one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
</ul>
<ul class="phrase2">
<li class="first">six</li>
<li>seven</li>
<li>eight</li>
</ul>
<ul class="phrase3">
<li>nine</li>
<li>ten</li>
<li>eleven</li>
<li>twelve</li>
</ul>

httpwebwitch

4:23 am on May 20, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Splitting the list into sub-lists isn't practical or semantically kosher. I don't know where the breaks will occur; it depends on the user's choice text size settings; if they have the font turned up larger, there'll be fewer phrases per line.

The actual data being shown is unknown. Think of it like a "tag cloud"... what I'm building is not really a tag cloud, but it should have the same kind of "word splatter" kind of look. Centered. With bullets between, but not at the edges. The data could be anything like...

<ul>
<li>one went to market</li>
<li>two stayed home</li>
<li>three had roast beast</li>
<li>four had none</li>
<li>five went wee wee wee</li>
</ul>

<ul>
<li>one for the money</li>
<li>two for the show</li>
<li>three to get ready</li>
<li>now go cat go</li>
</ul>

<ul>
<li>lorem ipsum</li>
<li>dolor</li>
<li>sinc et</li>
<li>omnibilius</li>
<li>car mata</li>
<li>petum set il</li>
<li>tado de trigil</li>
<li>filistra petrum e</li>
</ul>

it's one list, with list items that do not "break", wrapping within a confined horizontal space, centered, with glyphy bullets between them.

I was musing whether something could be done with margin-collapsing... hmm... no, I'm still stuck.

I'm beginning to wonder whether I'll have to get JavaScript involved.

SuzyUK

6:03 am on May 20, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



hmm ok, witchy, does sound tricky,

..it sounds like it might be a plan for inline-blocks, which would get your items wrapping and centering, but how to do the "delimiter", only sometimes, is then the problem, will have a think.. I had originally thought of negative margins too but can't see it working on variable lime lengths..will have another think.

SuzyUK

8:16 am on May 20, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



here's what I got without the script:

<style type="text/css" media="screen">
ul#cloud {
width: 400px;
margin: 0;
padding: 5px 0;
list-style: none;
background: #abc;
text-align: center;
}

ul#cloud li {
display: -moz-inline-box; /* For FF */
-moz-box-orient: vertical;
border: 1px solid #000;
display: inline-block;
padding: 0 20px;
margin: 5px -7px 5px -7px;
background: url(bullet.jpg) no-repeat 0 50%;
}

ul#cloud li.nooverlap {
background: transparent;
}

</style>

<!--[if lt IE 8]>
<style type="text/css" media="screen">
ul#cloud li {display: inline;}
</style>
<![endif]-->

</head>
<body>
<ul id ="cloud" >
<li>one widget</li>
<li>two little widgets</li>
<li>three big</li>
<li>four odd numbers</li>
<li>five noses</li>
<li>six </li>
<li>seven</li>
<li>eight</li>
<li>nine</li>
<li>ten</li>
<li>eleven</li>
<li>twelve</li>
</ul>

That just shows (using negative margins where the glyphs should go)

so afaik, which isn't a lot about scripting ;) it might just be a case of finding the top positions of each of the li's and comparing it to its previous sibling if tops aren't the same (or differ by more than a whole line length?) or if there's no previous sibling, then it's a new line/first item in line so apply the class name which removes the background image (nooverlap)

not sure if left positions even need to be involved, but that depends of if it really is a cloud where the li elements might actually be different heights? This could be flawed logic but you'll know that better than me ;)

[edited by: SuzyUK at 8:18 am (utc) on May 20, 2008]

httpwebwitch

5:46 pm on May 21, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I added a pinch of JS to add classes based on the Y-axis position, and managed to get something working in Firefox. But it all went haywire in IE. IE doesn't seem to like the display type "inline-block"

IE7 doesn't respect the left-padding on wrapped elements. Some lines have the bullet appended to the left, others do not. It's hard to explain.

Anyhow, I'm satisfied that it's not possible using CSS only, and I can take it from here.

Thanks swa66, P1R, and SuzyUK!

Dave75

7:43 am on May 28, 2008 (gmt 0)

10+ Year Member



The solution you're after looks like this. Of course, its not going to work in crappy browsers like IE:


<ul>
<span>
<li>one</li>
<li>two</li>
<li class="last">three</li>
</span>
<span>
<li>four</li>
<li>five</li>
<li class="last">six</li>
</span>
<span>
<li>seven</li>
<li>eight</li>
<li class="last">nine</li>
</span>
</ul>

ul{text-align:center;}
li{list-style:none;display:inline;padding:0;}
span{display:block;}
li:after{content:" * ";}
li.last:after{content:"";}

swa66

11:35 am on May 28, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Dave75,

The OP was after a way to do it without those spans (or anything replacing them)

Finally, if you're ditching IE, you don't need to put a class on the last child to select it seperately, there's a standard pseudoclass ":last-child".
Since IE7 doesn't do :last-child (only does :first-child) it's sometimes easier to revert it, and not use ":after", but ":before", and make the first one "special". That way IE7 has a chance to play along.
As usual: there's little hope for IE6.

Remember: MSFT is after your first born only ;-)

httpwebwitch

6:28 pm on May 28, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Right ...

if I was able to do this

<ul> 
<span>
<li>one</li>
<li>two</li>
<li class="last">three</li>
</span>
<span>
<li>four</li>
<li>five</li>
<li class="last">six</li>
</span>
<span>
<li>seven</li>
<li>eight</li>
<li class="last">nine</li>
</span>
</ul>

then I'd just do this instead

<ul> 
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
<ul>
<li>four</li>
<li>five</li>
<li>six</li>
</ul>
<ul>
<li>seven</li>
<li>eight</li>
<li>nine</li>
</ul>

The point of the exercise is that I can't determine where in the list those items will be "broken" or wrapped onto new lines. And CSS doesn't have a pseudo-class for it either. The only working method I've found is to loop through the list items with JavaScript and test the "top" position of each, so I can inject a class attribute into the first item on each wrapped line.

My conclusion is this isn't a visual style that can be pulled off with CSS alone. I would love to be proven wrong.