CSS Font Border?
Asked Answered
T

12

603

With all the new CSS3 border stuff going on (-webkit, ...) is it now possible to add a border to your font? (Like the solid white border around the blue Twitter logo). If not, are there any not-too-ugly hacks that will accomplish this in CSS/XHTML or do I still need to fire up Photoshop?

Titian answered 3/4, 2010 at 10:35 Comment(0)
B
1198

There's an experimental CSS property called text-stroke, supported on some browsers behind a -webkit prefix.

h1 {
    -webkit-text-stroke: 2px black; /* width and color */

    font-family: sans; color: yellow;
}
<h1>Hello World</h1>

Another possible trick would be to use four shadows, one pixel each on all directions, using property text-shadow:

h1 {
    /* 1 pixel black shadow to left, top, right and bottom */
    text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;

    font-family: sans; color: yellow;
}
<h1>Hello World</h1>

But it would get blurred for more than 1 pixel thickness.

Bernie answered 24/11, 2010 at 17:42 Comment(10)
this worked for me pefrectly, I added only 1px "blur":text-shadow: -1px 0 1px black, 0 1px 1px black, 1px 0 1px black, 0 -1px 1px blackSeaborg
great if you only need a 1px border. But it gets ugly when using 2px or more.Hermanhermann
Note: there is a bug with the Andriod browser (code.google.com/p/android/issues/detail?id=7531), if you set the "blur" to be 0px, then no outline appears at all.Scat
btw, you can find this code in W3C CSS tip page w3.org/Style/Examples/007/text-shadow.en.html (under DRAWING LETTERS AS OUTLINES part)Lantha
I've found this works best on a color background and @pixelass's answer works best with an image backgroundWasher
What is actually happening?Bridgers
@DaniSpringer The text is re-written in black at the listed offsets underneath the yellow text.Candlepower
This -lazy- (imho) answer (but upvoted by me as well) needs elaboration. A newbie can't know what the numbers are about.Focalize
The text-shadow method worked perfect for me in ChromeSuperego
text-shadow looks better, but when using a font-color with opacity, text-stroke is the only solutionMehalek
B
186

UPDATE

Here's a SCSS mixin to generate the stroke: http://codepen.io/pixelass/pen/gbGZYL

/// Stroke font-character
/// @param  {Integer} $stroke - Stroke width
/// @param  {Color}   $color  - Stroke color
/// @return {List}            - text-shadow list
@function stroke($stroke, $color) {
  $shadow: ();
  $from: $stroke*-1;
  @for $i from $from through $stroke {
   @for $j from $from through $stroke {
      $shadow: append($shadow, $i*1px $j*1px 0 $color, comma);
    }
  }
  @return $shadow;
}
/// Stroke font-character
/// @param  {Integer} $stroke - Stroke width
/// @param  {Color}   $color  - Stroke color
/// @return {Style}           - text-shadow
@mixin stroke($stroke, $color) {
  text-shadow: stroke($stroke, $color);
}

enter image description here

YES old question.. with accepted (and good) answers..

BUT...In case anybody ever needs this and hates typing code...

THIS is a 2px black border with CrossBrowser support (not IE) I needed this for @fontface fonts so it needed to be cleaner than previous seen answers... I takes every side pixelwise to make sure there are (almost) no gaps for "fuzzy" (handrawn or similar) fonts. Subpixels (0.5px) could be added but I don't need it.

Long code for just the border??? ...YES!!!

text-shadow: 1px 1px 0 #000,
    -1px 1px 0 #000,
    1px -1px 0 #000,
    -1px -1px 0 #000,
    0px 1px 0 #000,
    0px -1px 0 #000,
    -1px 0px 0 #000,
    1px 0px 0 #000,
    2px 2px 0 #000,
    -2px 2px 0 #000,
    2px -2px 0 #000,
    -2px -2px 0 #000,
    0px 2px 0 #000,
    0px -2px 0 #000,
    -2px 0px 0 #000,
    2px 0px 0 #000,
    1px 2px 0 #000,
    -1px 2px 0 #000,
    1px -2px 0 #000,
    -1px -2px 0 #000,
    2px 1px 0 #000,
    -2px 1px 0 #000,
    2px -1px 0 #000,
    -2px -1px 0 #000;
Baudoin answered 3/1, 2012 at 12:39 Comment(7)
updated the code due to a duplicate of 0 2px 0 #000 and it's -/+ elements. The blur (0 before #000) could be removed but I tend to keep it even if it's 0. I should also note that it's recommended to have a minified or compressed CSS version of your code on production sites and keep a commented uncompressed version for editing. The code above is a good example why a CSS code should be minified but needs to be separated line by line for editing.Baudoin
I played around with the '-webkit-text-stroke' property (mainly to make fonts look nicer on UGLY UGLY windows) Yet this made the loading times way too long and even crashed my site (mac Chrome 16). So I removed it faster than the page could even load. I guess this is only intended for single lines of fonts. (I was using it for 'body')Baudoin
Have you done any performance benchmarking with this? I've found text shadow to bog down the page when scrolling, for exampleHageman
@ChrisBosco -webkit- is really good with all kinds of CSS. I have experienced laggy scrolling on Opera and Firefox on some of my other hardcore CSS projects. mobile safari also seems to have a problem if a gradient, box-shadow or text-shadow has too many layers.Baudoin
I've found this works best on an image background and @Narcélio Filho's answer works best with a color backgroundWasher
This seems not to work as desired if your units provided are viewport-relative and not in pixels.Neysa
the original codepen "disappeared", so I created a new one with the original code from this post and also made a comparison of the other solutions mentioned here codepen.io/Grienauer/pen/GRRdRJrCathycathyleen
L
61

You could perhaps emulate a text-stroke, using the css text-shadow (or -webkit-text-shadow/-moz-text-shadow) and a very low blur:

#element
{
  text-shadow: 0 0 2px #000; /* horizontal-offset vertical-offset 'blur' colour */
  -moz-text-shadow: 0 0 2px #000;
  -webkit-text-shadow: 0 0 2px #000;
}

But while this is more widely available than the -webkit-text-stroke property, I doubt that it's available to the majority of your users, but that might not be a problem (graceful degradation, and all that).

Lurdan answered 3/4, 2010 at 10:51 Comment(1)
It should be noted that it is possible to totally omit the third argument in order to have no blur at all.Profundity
D
31

To elaborate more on some answers that have mentioned -webkit-text-stroke, here's is the code to make it work:

div {
  -webkit-text-fill-color: black;
  -webkit-text-stroke-color: red;
  -webkit-text-stroke-width: 2.00px; 
}

An in-depth article about using text stroke is here and a list of browsers that support text stroke is here.

Diazonium answered 18/4, 2012 at 12:7 Comment(0)
C
20

There seems to be a 'text-stroke' property, but (at least for me) it only works in Safari.

http://webkit.org/blog/85/introducing-text-stroke/

Countercurrent answered 3/4, 2010 at 10:44 Comment(0)
A
18

Here's what I'm using :

.text_with_1px_border
{
    text-shadow: 
        -1px -1px 0px #000,
         0px -1px 0px #000,
         1px -1px 0px #000,
        -1px  0px 0px #000,
         1px  0px 0px #000,
        -1px  1px 0px #000,
         0px  1px 0px #000,
         1px  1px 0px #000;
}

.text_with_2px_border
{
    text-shadow: 
        /* first layer at 1px */
        -1px -1px 0px #000,
         0px -1px 0px #000,
         1px -1px 0px #000,
        -1px  0px 0px #000,
         1px  0px 0px #000,
        -1px  1px 0px #000,
         0px  1px 0px #000,
         1px  1px 0px #000,
        /* second layer at 2px */
        -2px -2px 0px #000,
        -1px -2px 0px #000,
         0px -2px 0px #000,
         1px -2px 0px #000,
         2px -2px 0px #000,
         2px -1px 0px #000,
         2px  0px 0px #000,
         2px  1px 0px #000,
         2px  2px 0px #000,
         1px  2px 0px #000,
         0px  2px 0px #000,
        -1px  2px 0px #000,
        -2px  2px 0px #000,
        -2px  1px 0px #000,
        -2px  0px 0px #000,
        -2px -1px 0px #000;
}
Anecdotist answered 24/11, 2014 at 10:10 Comment(0)
D
10

Sorry I'm late, but speaking about text-shadow, I thought you would also like this example (I use it quite often when I need good shadows on text):

text-shadow:
    -2px   -2px lightblue,
    -2px -1.5px lightblue,
    -2px   -1px lightblue,
    -2px -0.5px lightblue,
    -2px    0px lightblue,
    -2px  0.5px lightblue,
    -2px    1px lightblue,
    -2px  1.5px lightblue,
    -2px    2px lightblue,
    -1.5px  2px lightblue,
    -1px    2px lightblue,
    -0.5px  2px lightblue,
    0px     2px lightblue,
    0.5px   2px lightblue,
    1px     2px lightblue,
    1.5px   2px lightblue,
    2px     2px lightblue,
    2px   1.5px lightblue,
    2px     1px lightblue,
    2px   0.5px lightblue,
    2px     0px lightblue,
    2px  -0.5px lightblue,
    2px    -1px lightblue,
    2px  -1.5px lightblue,
    2px    -2px lightblue,
    1.5px  -2px lightblue,
    1px    -2px lightblue,
    0.5px  -2px lightblue,
    0px    -2px lightblue,
    -0.5px -2px lightblue,
    -1px   -2px lightblue,
    -1.5px -2px lightblue;
Despondent answered 23/1, 2020 at 17:53 Comment(0)
M
4
text-shadow:
    1px  1px 2px black,
    1px -1px 2px black,
   -1px  1px 2px black,
   -1px -1px 2px black;
Mallon answered 20/4, 2014 at 9:23 Comment(0)
G
4

Since webkit seems to bug around for me, I wasn't satisfied with the answers. Then I found this codepen which can generate raw CSS for you. Just type in the color and border width in the JS and scroll down to the CSS output.

Example of 2px black text outline:

  text-shadow: -2px -2px 0 black,-2px -1px 0 black,-2px 0px 0 black,-2px 1px 0 black,-2px 2px 0 black,-1px -2px 0 black,-1px -1px 0 black,-1px 0px 0 black,-1px 1px 0 black,-1px 2px 0 black,0px -2px 0 black,0px -1px 0 black,0px 0px 0 black,0px 1px 0 black,0px 2px 0 black,1px -2px 0 black,1px -1px 0 black,1px 0px 0 black,1px 1px 0 black,1px 2px 0 black,2px -2px 0 black,2px -1px 0 black,2px 0px 0 black,2px 1px 0 black,2px 2px 0 black

Just in case the codepen gets removed (Vue.js):

new Vue({
  el: '#app',
  data: {
    width: 5,
    color: 'DeepPink',
    styles: ''
  },
  
  created() {
    this.textChange()
  },
  
  methods: {
    textChange() {
      var shadows = []
      var color = this.color
      
      for(let i = -this.width; i <= this.width; i++) {
        for(let j = -this.width; j <= this.width; j++) {
          shadows.push(`${i*1}px ${j*1}px 0 ${color}`)
        }
      }
      
      this.styles = shadows.join(',')
    }
  }
})

html:

<p><strong>text-shadow:</strong> {{styles}}</p>
Gummosis answered 17/11, 2021 at 6:29 Comment(0)
H
3

Stroke font-character with a Less mixin

Here's a LESS mixin to generate the stroke: http://codepen.io/anon/pen/BNYGBy?editors=110

/// Stroke font-character
/// @param  {Integer} $stroke - Stroke width
/// @param  {Color}   $color  - Stroke color
/// @return {List}            - text-shadow list
.stroke(@stroke, @color) {
  @maxi: @stroke + 1;
  .i-loop (@i) when (@i > 0) {
    @maxj: @stroke + 1;
    .j-loop (@j) when (@j > 0) {
      text-shadow+: (@i - 1)*(1px)  (@j - 1)*(1px) 0 @color;
      text-shadow+: (@i - 1)*(1px)  (@j - 1)*(-1px) 0 @color;
      text-shadow+: (@i - 1)*(-1px)  (@j - 1)*(-1px) 0 @color;
      text-shadow+: (@i - 1)*(-1px)  (@j - 1)*(1px) 0 @color;
      .j-loop(@j - 1);
    }
    .j-loop (0) {}
    .j-loop(@maxj);
    .i-loop(@i - 1);
  }
  .i-loop (0) {}
  .i-loop(@maxi);
  text-shadow+: 0 0 0 @color;
}

(it's based on pixelass answer that instead uses SCSS)

Hayott answered 3/7, 2015 at 8:53 Comment(0)
C
3

I created a comparison of all the solutions mentioned here to have a quick overview:

<h1>with mixin</h1>
<h2>with text-shadow</h2>
<h3>with css text-stroke-width</h3>

https://codepen.io/Grienauer/pen/GRRdRJr

Cathycathyleen answered 6/11, 2019 at 18:3 Comment(0)
P
1

I once tried to do those round corners and drop shadows with css3. Later on, I found it is still poorly supported (Internet Explorer(s), of course!)

I ended up trying to do that in JS (HTML canvas with IE Canvas), but it impacts the performance a lot (even on my C2D machine). In short, if you really need the effect, consider JS libraries (most of them should be able to run on IE6) but don't over do it due to performance issues; if you still need an alternative... you could use SFiR, then PS it and SFiR it. CSS3 isn't ready today.

Pythia answered 3/4, 2010 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.