W3C home > Mailing lists > Public > www-style@w3.org > January 2010

Re: Text selector [was Re: breaking overflow]

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Wed, 6 Jan 2010 10:39:26 -0600
Message-ID: <dd0fbad1001060839q128b55d3s4c494cfeda6fb6fd@mail.gmail.com>
To: Brad Kemper <brad.kemper@gmail.com>
Cc: "robert@ocallahan.org" <robert@ocallahan.org>, Bobby Jack <bobbykjack@yahoo.co.uk>, Boris Zbarsky <bzbarsky@mit.edu>, www-style list <www-style@w3.org>
On Tue, Jan 5, 2010 at 5:40 PM, Brad Kemper <brad.kemper@gmail.com> wrote:
>> or
>> p::text('ABCD') { color:red; }
>> p::text('CDEF') { color:blue; }
>> <p>ABCDEF</p>
> Tab and I resolved this to our own general satisfacion, I thought, in the
> earlier part of the thread. "AB" would be red and "CDEF" would be blue.

No, after further thought this isn't resolved properly.  What's the
behavior if both ::text() selectors applied display:block; to the
content?  Colors override each other nicely; display changes do not.
You'd end up with precisely the problem I was decrying earlier about
allowing it to match across element boundaries - it would display as:


This would be very confusing to authors.

>> I think a good way to address your use case would be to extend the "content"
>> property as applied to elements, so we can replace the contents of an
>> element with children with different styles. Right now CSS3 supports, for
>> example,
>> h1 { content: url(welcome.png) " to my " url(page.png); font:...; }
>> With creative use of :before and :after you can have
>> h1:before { content: "Welcome"; font:...; }
>> h1 { content: " to my "; font:...; }
>> h1:after { content: "Page"; font:...; }
>> We could extend this to support an unlimited number of different child
>> pseudo-elements.
> As I said, that is but a single use case out of many.

That addresses my main use-case, though.  It would be kinda weird, but
it would work.  I'd start with markup like this:

<h1>iGo Figure Webportal - Know more about your business...from
anywhere in the world.</h1>

And then style it like this:
h1 { content: url(foo); font-size: 18px;}
h1::after::before { content: "Know more "; font-weight: bold; font-size: 27px; }
h1::after { content: "about your business..."; font-weight: normal;
position: absolute; top: x; left: y; }
h1::after(2)::before { content: "from anywhere "; font-weight: bold;
font-size: 27px; }
h1::after(2) { content: "in the world."; position: absolute; top: x; left: y; }

Requires a more complete implementation of Generated Content, but it
would work, and it would be unambiguous since we're setting up the
boxes explicitly.  It's a problem that our content is leaking out into
our stylesheet, so that we'll have to update it in both places, but
shrug.  That's the price paid for tying styling to non-semantic
divisions.  You either have content in your styling, or styling in
your content (via meaningless <span>s).  It's up to you which is the
lesser evil.  (The content would still appear in the stylesheet with
::text, just in the selector rather than in the content: property.)

>>> Here was something I showed earlier:
>>> ::text("Example \d: *\n") {
>>>  display: block;
>>>  padding: .5em;
>>>  margin: 1 em 0;
>>>  border: 1px solid #999;
>>>  background-color: #eee;
>>> }

This probably should be marked up semantically.

>>> Here is a way to highlight the company name whenever it appears in a
>>> paragraph or list item:
>>> p::text("ACME"), li::text("ACME") { background-color: yellow; }

This is more borderline.  It's possible that it should just be done up
with <b> each time.

>>> Here is a way to use a mono-spaced font for numbers:
>>> p::text("\d+") { font-family: "Courier New", Courier, monospace; }

This one is indeed a pure styling issue.  It could perhaps be
addressed another way, though, by having something targetting
number-styling directly, either as a specialized selector or as a
number-style property or similar.

>>> Here is a way to turn a greater-than glyph into a picture of a hand
>>> pointing right:
>>> ::text(">") {
>>>    height:20px; width:40px;
>>>    background-image:url(right-pointing-hand.png);
>>>    display:inline-block;
>>>    color: transparent;
>>> }

Why aren't you using the picture for your breadcrumb separators
anyway?  As well, why are breadcrumb separator in the content anyway?
I do my breadcrumbs as an <ol>, with the <li>s made inline, the list
markers removed, and breadcrumb markers inserted with ::before.  The
markers aren't content in the first place.

>>> Here is a way to quickly strike out your old phone number throughout the
>>> site, until you've had a chance to update it, or in case you suspect that it
>>> is still on some of the hundreds of pages you don't control but provide CSS
>>> files for:
>>> ::text("\(555\) 555-5555") { text-decoration: line-through; }

This is best accomplished with a search-and-replace across your
website.  If you don't have access to some pages, you have a problem
that needs to be solved *there*, rather than being hacked around with
a CSS backdoor.  Users of non-CSS browsers won't know that this phone
number is now 'obsolete'.

Now that it's been pointed out that my main use-case for ::text
(fancy, non-semantic styling of page headers) can be addressed equally
well by using generated content, and without any of the inherent
ambiguities of a full-powered ::text, I'm seeing a lot less use for
it.  Using it as a pure-inline element with restrictions similar to
::first-line might still be cool, but I'm much less convinced of its
usefulness now.  (Though, a lot of the badness of ::first-line doesn't
apply here, since this is content-based, not structure-based; you
can't apply styling via it that changes what it matches, like you can
with first-line and, say, font-size.)

Received on Wednesday, 6 January 2010 16:39:54 UTC

This archive was generated by hypermail 2.4.0 : Friday, 25 March 2022 10:07:42 UTC