95

This one has me kind of stumped. I want to make the first word of all the paragraphs in my #content div at 14pt instead of the default for the paragraphs (12pt). Is there a way to do this in straight CSS or am I left wrapping the first word in a span to accomplish this?

Paulie_D
  • 107,962
  • 13
  • 142
  • 161
dragonmantank
  • 15,243
  • 20
  • 84
  • 92
  • Example: https://medium.com/china-media-project/fact-checking-against-the-fact-of-ccp-rule-6381588c7cac#b852 – Pacerier Apr 25 '16 at 20:32

14 Answers14

103

What you are looking for is a pseudo-element that doesn't exist. There is :first-letter and :first-line, but no :first-word.

You can of course do this with JavaScript. Here's some code I found that does this: http://www.dynamicsitesolutions.com/javascript/first-word-selector/

Roman Snitko
  • 3,655
  • 24
  • 29
Robby Slaughter
  • 1,530
  • 1
  • 11
  • 9
  • Why wouldn't they have specified a :first-word in the spec? – alex Mar 17 '09 at 00:25
  • 75
    Probably because a "word" is not a well-defined concept in a layout language. Is "half-baked" one word or two? What about "McDonald" and "O'Shea"? What's the first word in "5 + 3 = 8" or "5+3=8"? – Robby Slaughter May 19 '09 at 23:36
  • 60
    For layout purposes, the definition of a word as: "a group of non-whitespace characters following and preceding whitespace characters" is a good one and highly usable. For processing you might need to be "thoughtful", but for layout it's a perfectly good solution. – Henrik Erlandsson Apr 20 '11 at 09:10
  • 2
    @Robby Slaughter Regular Expression do it pretty well with \d and \w – FMaz008 Aug 01 '11 at 18:57
  • 16
    There are no spaces between words of Chinese characters. 實際上,漢字沒有單詞和字母的概念. – deerchao May 10 '12 at 15:47
  • 67
    @RobbySlaughter CSS has already been defining the concept of a "word" (at least for Latin alpha characters) for as long as `text-transform: capitalize` has been around: http://jsfiddle.net/mlms13/DRJ76/ – Michael Martin-Smucker Jun 25 '12 at 15:35
  • 1
    Just because it's slightly hard to define doesn't mean it shouldn't be done. But that's just CSS as usual... – Jonathan. Aug 14 '12 at 11:26
  • 22
    A "word" is very well defined in browsers. An implementation of :first-word would simply utilise the same logic used in line breaks. – Lachlan Arthur Sep 11 '12 at 04:22
  • should be able to tell how many first words. word: all letters before space. like `p:first-word(3){}` so= `this is selected` this is not – Muhammad Umer Aug 06 '13 at 04:14
  • 1
    Should have all the standard selectors, `:nth-word(3n+1)`, `:last-word`, `:first-word` and do the same for letters. While we have `:first-letter`, we should also have `:last-letter` and `:nth-letter(3n+1)`. – Robert McKee Mar 25 '14 at 20:51
  • @RobbySlaughter - it's better to give support for most cases than not at all, therefor the claim that a "word" is not a well-defined concept doesn't matter much. They could have defined it in a minute and add support, doesn't need to be perfect. – vsync Jun 15 '16 at 08:04
  • @RobbySlaughter That is fake news! Computers knows what's a word and they one they will take over the world. – Arnaldo Capo Oct 18 '17 at 15:10
  • 2
    it is now 2018 and we still don't have this feature in CSS – RozzA Feb 13 '18 at 21:12
38

I have to disagree with Dale... The strong element is actually the wrong element to use, implying something about the meaning, use, or emphasis of the content while you are simply intending to provide style to the element.

Ideally you would be able to accomplish this with a pseudo-class and your stylesheet, but as that is not possible you should make your markup semantically correct and use <span class="first-word">.

Prestaul
  • 83,552
  • 10
  • 84
  • 84
  • 4
    The javascript answer accepted as correct is potentially more useful, but I believe this one to be the most semantically correct. – Reynolds Dec 21 '09 at 16:35
  • 14
    FWIW, the `` element may be appropriate. The [HTML5 spec](http://www.w3.org/TR/html5/text-level-semantics.html#the-b-element) says: _The b element represents a span of text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood, such as key words in a document abstract, product names in a review, actionable words in interactive text-driven software, or **an article lede**._ (emphasis mine) The first word isn't quite an article lede, but its function is the same. – mattsoave Jan 26 '14 at 07:49
  • Very nice, @mattsoave. I hadn't seen the redefinition of `` in html5 yet, so that is very interesting. I'll keep that in my bag of tricks next time I need a styled element with no real semantic meaning. – Prestaul Jan 28 '14 at 17:15
  • 1
    @mattsoave - I know it's 5+ years later, but I noticed how stackoverflow uses a b element for your emphasis :-) – Herbert Van-Vliet Dec 15 '19 at 22:59
  • @Prestaul Your span suggestion is more or less what I'm doing now. However when screen is resized smaller, a middle word now becomes a first word. As your answer was written in 2008 I wonder if there is a new way of doing it? – WinEunuuchs2Unix Dec 03 '21 at 23:40
  • @WinEunuuchs2Unix Nope. Going into 2022 there is still really only one option and that is to wrap the first word in an element and style that. Of course this can be done with js but, if you have the option, just add it to your markup and avoid the js overhead and possible FOUC. – Prestaul Dec 06 '21 at 16:48
24

Same thing, with jQuery:

$('#links a').each(function(){
    var me = $(this);
    me.html( me.text().replace(/(^\w+)/,'<strong>$1</strong>') );
  });

or

$('#links a').each(function(){
    var me = $(this)
       , t = me.text().split(' ');
    me.html( '<strong>'+t.shift()+'</strong> '+t.join(' ') );
  });

(Via 'Wizzud' on the jQuery Mailing List)

Jon Hadley
  • 5,196
  • 8
  • 41
  • 65
  • 1
    Seems like the best solution for me. BTW: this will not work with, ie. slovak characters, like "Zimná záhrada". So I used this regex instead: "([^\s]+)" – Patrik Krehák Feb 23 '16 at 14:01
12

Sadly even with the likes of CSS 3 we still do not have the likes of :first-word :last-word etc using pure CSS. Thankfully there's almost a JavaScript nowadays for everything which brings me to my recommendation. Using nthEverything and jQuery you can expand from the traditional Pseudo elements.

Currently the valid Pseudos are:

  • :first-child
  • :first-of-type
  • :only-child
  • :last-child
  • :last-of-type
  • :only-of-type
  • :nth-child
  • :nth-of-type
  • :nth-last-child
  • :nth-last-of-type

And using nth Everything we can expand this to:

  • ::first-letter
  • ::first-line
  • ::first-word
  • ::last-letter
  • ::last-line
  • ::last-word
  • ::nth-letter
  • ::nth-line
  • ::nth-word
  • ::nth-last-letter
  • ::nth-last-line
  • ::nth-last-word
Simon Hayter
  • 3,131
  • 27
  • 53
8

You have to wrap the word in a span to accomplish this.

hazzen
  • 17,128
  • 6
  • 41
  • 33
8

Pure CSS solution:

Use the :first-line pseudo-class.

display:block;
Width:40-100px; /* just enough for one word, depends on font size */
Overflow:visible; /* so longer words don't get clipped.*/
float:left; /* so it will flow with the paragraph. */
position:relative; /* for typeset adjustments. */

Didn't test that. Pretty sure it will work fine for you tho. I've applied block rules to pseudo-classes before. You might be stuck with a fixed width for every first word, so text-align:center; and give it a nice background or something to deal with the negative space.

Hope that works for you. :)

-Motekye

Motekye Guakein
  • 154
  • 1
  • 3
  • 1
    1) That's a pseudo-element 2) That's for the first **line**. – BoltClock Nov 23 '11 at 14:29
  • 14
    The idea is to make the first line wide enough for only one word, float it so it runs with the rest of the text, then apply styles. Jeez. – Motekye Guakein Nov 23 '11 at 16:37
  • 2
    A very creative idea but you should test before you post. It doesn't work - and it can't work because `display` is ignored in `::first-line` (https://developer.mozilla.org/de/docs/Web/CSS/::first-line). – wortwart Jan 14 '15 at 14:17
  • 4
    Wide enough "just for one word"? That's ridiculous, as a word can be 1 letter or 15 letters. – jbyrd Mar 23 '17 at 16:48
2

Here's a bit of JavaScript and jQuery I threw together to wrap the first word of each paragraph with a <span> tag.

$(function() {
    $('#content p').each(function() {
        var text = this.innerHTML;
        var firstSpaceIndex = text.indexOf(" ");
        if (firstSpaceIndex > 0) {
            var substrBefore = text.substring(0,firstSpaceIndex);
            var substrAfter = text.substring(firstSpaceIndex, text.length)
            var newText = '<span class="firstWord">' + substrBefore + '</span>' + substrAfter;
            this.innerHTML = newText;
        } else {
            this.innerHTML = '<span class="firstWord">' + text + '</span>';
        }
    });
});

You can then use CSS to create a style for .firstWord.

It's not perfect, as it doesn't account for every type of whitespace; however, I'm sure it could accomplish what you're after with a few tweaks.

Keep in mind that this code will only execute after page load, so it may take a split second to see the effect.

user1171848
  • 276
  • 3
  • 10
2

Use the strong element, that is it's purpose:

<div id="content">
    <p><strong>First Word</strong> rest of paragraph.</p>
</div>

Then create a style for it in your style sheet.

#content p strong
{
    font-size: 14pt;
}
Dale Ragan
  • 18,202
  • 3
  • 54
  • 70
1

There isn't a plain CSS method for this. You might have to go with JavaScript + Regex to pop in a span.

Ideally, there would be a pseudo-element for first-word, but you're out of luck as that doesn't appear to work. We do have :first-letter and :first-line.

You might be able to use a combination of :after or :before to get at it without using a span.

Rob Allen
  • 17,381
  • 5
  • 52
  • 70
1

An easy way to do with HTML+CSS:

TEXT A <b>text b</b>

<h1>text b</h1>

<style>
    h1 { /* the css style */}
    h1:before {content:"text A (p.e.first word) with different style";    
    display:"inline";/* the different css style */}
</style>
Joundill
  • 6,828
  • 12
  • 36
  • 50
0

You can select first Letter or Line

p::first-letter {
  font-weight: bold;
  color: red;
}

https://css-tricks.com/almanac/selectors/f/first-letter/

M K
  • 61
  • 6
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 01 '21 at 12:08
0

I find JavaScript being the best way to achieve this. Below is the JS code to set an element's First Word as the element's innerText

let text = document.querySelector('.menu_text');
const words = menu_text.innerHTML.toString().split(' ');
text.innerText = words[0];
Schäfer
  • 181
  • 1
  • 1
  • 7
0

My idea to make it possible is use a php function to get a first word of the string and then use a CSS styling to give this word different color. Here how i use this for H1 tag. Here how you can get first word if you work on PHP.

<?php  
    $string = "Read more";
    echo '<h1><span>' . strtok($string, " ") . '</span>' . $string . '</h1>'; 
?>

CSS

h1 {
    position: relative;
    display: inline-block;
    margin: 0;
}
h1 > span {
    position: absolute;
    color: blue;
    text-shadow: 0px 0px 1px blue;
}

Here is the snippet only for demonstration how it looks when your PHP script will return the HTML code on your page or you want use only a HTML.

h1 {
    position: relative;
    display: inline-block;
    margin: 0;
}
h1 > span {
    position: absolute;
    color: blue;
    text-shadow: 0px 0px 1px blue;
}
<h1><span>Read</span>Read more</h1>
X9DESIGN
  • 774
  • 1
  • 10
  • 23
-1

Insert Span Tag in your paragraph text. For Example- <p><span>Hello</span>My Name Is Dot</p and then style the first letter.

Ashique
  • 345
  • 1
  • 8
  • OP is asking for a selector. His question said: "Is there a way to do this in ***straight*** CSS” [emphasis mine]. – VorganHaze Aug 16 '20 at 23:27