8

I have a strange problem and I am not sure how to resolve it. I would like to get the first character of a Text field I get from a Database. With this character, I would apply a CSS style to make it big.

If you try this following code, you will understand what is my problem:

<?php
$str_en = "I am a sentence.";
echo $str_en[0];

echo "<br /><br />";

$str_fr = "À tous les jours je fais du PHP.";
echo $str_fr[0];

echo "<br /><br />";

$str_fr = "Étais-tu ici?";
echo $str_fr[0];
?>

The code Above will output:

I

Ã

Ã

It seems like that a French character is using more than one bytes in a string. The problem is that not all my sentence start with a French character. Anyone have an idea how I could have a function that convert this:

<?php
$str_fr = "Étais-tu ici?";
?>

To this

$str_fr = "<span class='firstletter'>É</span>tais-tu ici?";

Or perhaps there is a better way with CSS3 to do this.

Etdashou
  • 5,095
  • 1
  • 17
  • 15
  • 2
    In addition to the specific answer using PHP multibyte string functions, you might also want to read [Joel's "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)"](http://www.joelonsoftware.com/articles/Unicode.html). – Matt Gibson Apr 19 '13 at 22:35

3 Answers3

16

See for mb_substr (http://www.php.net/manual/en/function.mb-substr.php)

$first_char = mb_substr($string, 0, 1, 'utf-8'); // You may change the forth parameter according to your needed encoding.

mb_substr repects the encoding and returns all the bytes representing the first character here.


CSS3 has a pseudo-class ::first-letter which selects only the first letter.

Example:

Your HTML is:

<p id="french_text">Étais-tu ici?</p>

Then you can address it with CSS3 by:

p:first-letter { /* Your properties */ }

(P.s.: Nowadays' standard is using ::first-letter (double double colon instead of a single double colon), but for best backwards compability use only one double colon)

bwoebi
  • 23,637
  • 5
  • 58
  • 79
  • You always need to call the mb_string functions with the encoding specified the string is using. Otherwise the result for anybody trying the code is *likely broken*. – hakre Apr 19 '13 at 22:39
  • @hakre Yes, but I don't know the encoding which is being used here. So I have only added an inline comment. (Btw. nowadays internal encoding should be more and more utf-8...) – bwoebi Apr 19 '13 at 22:41
  • @bwoebi you can infer it from his output. UTF-8. The first byte of UTF-8 encoded "É" and "À", when interpreted as Windows-1252, shows up as Ã. – Esailija Apr 19 '13 at 22:41
  • @bwoebi: Specify it anway, so that it's clear in the example code. You don't need to provide a working solution with your answer, just a correct one. Here as this is a character encoding related issue, specify the encoding. Because not doing so often is the problem ;) – hakre Apr 19 '13 at 22:42
  • @Esailija maybe, I don't know it... (but I could have tested it on the console, right :/) – bwoebi Apr 19 '13 at 22:42
  • Note that the CSS3 standard pseudo-element with 2 colons is not supported in IE<9, whereas the old version with one colon (`:first-letter`) is supported since IE 5.5 and has the same effect across all browsers. https://developer.mozilla.org/en-US/docs/CSS/::first-letter#Browser_compatibility – Fabrício Matté Apr 19 '13 at 22:43
  • @hakre added `'utf-8'` in the answer. – bwoebi Apr 19 '13 at 22:46
  • 1
    @FabrícioMatté Added some note about it in my answer. – bwoebi Apr 19 '13 at 22:47
  • 1
    I wanted to thank you. I used the CSS :first-letter and I also learned about mb_substr(). – Etdashou Apr 20 '13 at 10:36
1

The output should have been:

I

�

�

You can fix that by doing

<?php
header("Content-Type: text/html; charset=utf-8");

Currently your source is in UTF-8 but browser interprets it as Windows-1252.

You can then do $first_char = mb_substr($string, 0, 1, "UTF-8"); to complete your problem.

Esailija
  • 138,174
  • 23
  • 272
  • 326
1

You better apply the :first-letter pseudo class to the container element. It's supported by all major browsers and does not mess up your HTML. For instance if you have a list with items as:

<ul>
     <li>First db term</li>
     <li>Second db term</li>
</ul>

You apply the first-letter CSS to each li element as:

ul li:first-letter { font-size: 3em }
Clarence
  • 2,944
  • 18
  • 16