363

I have a tag in my html like this:

<h1>My Website Title Here</h1>

Using css I want to replace the text with my actual logo. I've got the logo there no problem via resizing the tag and putting a background image in via css. However, I can't figure out how to get rid of the text. I've seen it done before basically by pushing the text off the screen. The problem is I can't remember where I saw it.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Micah
  • 111,873
  • 86
  • 233
  • 325
  • 3
    there are lots of outdated answers here: consider upvoting the more recent answer https://stackoverflow.com/a/27769435/2586761 to expose it – ptim Feb 09 '17 at 00:15

31 Answers31

454

This is one way:

h1 {
    text-indent: -9999px;                 /* sends the text off-screen */
    background-image: url(/the_img.png);  /* shows image */
    height: 100px;                        /* be sure to set height & width */
    width: 600px;
    white-space: nowrap;            /* because only the first line is indented */
}

h1 a {
    outline: none;  /* prevents dotted line when link is active */
}

Here is another way to hide the text while avoiding the huge 9999 pixel box that the browser will create:

h1 {
    background-image: url(/the_img.png);  /* shows image */
    height: 100px;                        /* be sure to set height & width */
    width:  600px;

    /* Hide the text. */
    text-indent: 100%;
    white-space: nowrap;
    overflow: hidden;
}
Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58
nicholaides
  • 19,211
  • 12
  • 66
  • 82
  • 6
    long titles will have an issue with this method since only the text before word-wrap is indented, and the W3C spec doesn't specify a situation for negative indent so this could have unpredictable results – Chris Farmiloe Jan 23 '09 at 01:34
  • 3
    If you use this method, you should add "overflow: hidden" to prevent seird selection box shooting off to the left (especially with links) – willoller Jan 23 '09 at 04:03
  • 4
    If you have any links in elements with the negative text-indent, make sure you also specify "outline: none" otherwise you get a dotted border going off the left of screen. – nickf Jan 23 '09 at 04:20
  • 9
    I prefer to use 'text-indent: -9999px;' just to make sure the text goes really far off the screen. A bit of defensive paranoia. – Andy Ford Jan 23 '09 at 08:15
  • 4
    Also add 'white-space: nowrap' just to be on the safe side if your text is long as only the first line is indented. – Andrew Moore May 08 '09 at 13:38
  • 3
    To further support the claim that "this is the proper way", see this excellent question for details about screen reader compatibility: http://stackoverflow.com/questions/1755656/displaynone-vs-visibilityhidden-vs-text-indent9999-how-screen-reader-behave-w – Jordan Lev Nov 09 '11 at 03:27
  • @Jordan Lev: I'm not however, if given outline: none; is a proper way of doing this. Removing outline ? – MEM Jun 22 '12 at 16:43
  • 2
    Also, use 'text-align: left' otherwise the text may not move. – sparebytes Aug 17 '12 at 15:37
  • A possible side-effect of this in WebKit is large layers detrimental to resource constrained rendering (source: http://www.youtube.com/watch?v=xuMWhto62Eo @ 35:30). – Regis Frey Aug 22 '12 at 16:45
  • 1
    I had some trouble with Firefox still not completely hiding the text, so I changed text-indent to 200% and it worked just fine. – aalaap Dec 14 '13 at 17:43
  • what about adding "color: transparent;" ? – Pola Edward Mar 22 '14 at 00:46
  • Jeffrey Zeldman suggests not to use -9999px; as it is more resource intensive than -100%; More info below. – chocolata Nov 14 '14 at 15:03
  • 1
    So after 7 years of this being a possibility in HTML to solve this issue, is this still a 'proper' way of fixing it (now that we got HTML5)? – Barrosy Apr 15 '16 at 11:14
  • If your text contains `
    `s, the text after those breaks stay visible
    – Richard de Wit Oct 06 '16 at 11:49
  • Does not work after
    so the other solutions should have much more votes
    – Dan Froberg Mar 20 '23 at 13:02
231

Why not simply use:

h1 { color: transparent; }
nesono
  • 2,489
  • 1
  • 13
  • 6
228

Just add font-size: 0; to your element that contains text.

.hidden { font-size: 0; }
  font-size: 0; hides text. <span class="hidden"> You can't see me :) </span>
valk
  • 9,363
  • 12
  • 59
  • 79
  • 1
    This is exactly what I needed. I wanted to hide what was in a div, but show what was in the child spans (to hide the punctuation between them). – mskfisher Sep 29 '11 at 23:24
  • 3
    This seems like the most logical (read: Least Bizarre) method -- however, I wonder how well it's supported in various browsers? (I can confirm it works in Firefox.) – Brian Lacy Apr 27 '12 at 17:34
  • 1
    It still shows the text very small in a more browsers than just IE7, this is not a complete cross browser solution. – macguru2000 Oct 25 '12 at 23:47
  • 8
    I have tested {font-size:0} trick in Chrome 27, Firefox 17, Safari for windows 5.1.7, Opera 12.12, IE8, IE9, IE10 - it works in all those browsers. This trick is best if you can't set the background-image on the element itself (e.g. because you are using tightly-packed sprite image and the required icon doesn't have enough empty padding around it), and have to use pseudo selector, e.g. element:after to display the background image. – beluga Jan 22 '13 at 15:35
  • 1
    This also changes the size of the div, so I do not recommend this. – Stephan Bijzitter Mar 26 '15 at 08:42
  • For some reason, this trick added space above `.myElement` when I tried it. – Flimm Jun 16 '16 at 12:43
  • i think this solution is the best one if you want to take some text offscreen. I tried the accepted answer solution but to my surprise, I had a horizontal scrollbar leading me to where my hidden text is. – Charmie Jan 23 '17 at 06:37
  • nice idea, thumb up – Firas Nizam Jan 06 '22 at 15:21
  • The problem with this approach is that `font-size` is often set at the beginning of a common.css for specific note types (`body`, `label`, ...). Those will have higher specificity and cause the .hidden to be overridden. Even simply a browser override for font-size could cause this ... – YoYo Dec 20 '22 at 22:22
36

The most cross-browser friendly way is to write the HTML as

<h1><span>Website Title</span></h1>

then use CSS to hide the span and replace the image

h1 {background:url(/nicetitle.png);}
h1 span {display:none;}

If you can use CSS2, then there are some better ways using the content property, but unfortunately the web isn't 100% there yet.

Robert
  • 1,286
  • 1
  • 17
  • 37
Chris Farmiloe
  • 13,935
  • 5
  • 48
  • 57
  • But be sure to also set the width and height attribute to that of the image - and make sure "padding" and "margin" are set because browsers have different ideas as to how much padding/margin a H1 tag needs to have. –  Jan 23 '09 at 01:28
  • The drawback here is if images are turned off, or if a css-aware bot shows up, the title won't be visible. – willoller Jan 23 '09 at 04:05
  • 14
    The important text within display none will probably be missed by search engine bots and screen readers. Use text-indent instead. – dylanfm Jan 23 '09 at 04:47
  • 1
    This wont do a thing, OP might as well remove the text in the title. Screen readers don't do anything with display none.. – Idris Dopico Peña Nov 21 '17 at 11:32
32

Hiding text with accessibility in mind:

In addition to the other answers, here is another useful approach for hiding text.

This method effectively hides the text, yet allows it to remain visible for screen readers. This is an option to consider if accessibility is a concern.

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    border: 0;
}

It's worth pointing out that this class is currently used in Bootstrap 3.


If you're interested in reading about accessibility:

Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • 1
    Sources for bs4 and h5bp: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css#L128, https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_screen-reader.scss#L5 – ptim Feb 09 '17 at 00:11
  • This works well for adding an element is screen-reader only; however, it does not work with the original question where an image is to be displayed by a background image specified in css. – vossad01 May 29 '17 at 02:59
  • @vossad01 - If you can't add another element, and you are stuck with a single element (like in the case that you mentioned), then one good workaround would be to utilize a [pseudo-element](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)... also, I posted this answer 6 years after the initial question was asked, and my answer was intended to target a broader audience since this question appears to be popular. – Josh Crozier May 29 '17 at 03:08
26

you can simply hide your text by add this attribute:

font-size: 0 !important;
Karol S
  • 9,028
  • 2
  • 32
  • 45
Omid Ahmadyani
  • 1,430
  • 13
  • 15
25

Jeffrey Zeldman suggests the following solution:

.hide-text {
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
}

It should be less resource intensive than -9999px;

Please read all about it here:

http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/

chocolata
  • 3,258
  • 5
  • 31
  • 60
16

So many complicated solutions.

The easiest one is simply to use:

color:rgba(0,0,0,0)
Pier
  • 10,298
  • 17
  • 67
  • 113
14

See mezzoblue for a nice summary of each technique, with strengths and weaknesses, plus example html and css.

Kyle
  • 3,935
  • 2
  • 30
  • 44
darasd
  • 2,899
  • 3
  • 26
  • 39
6

Do not use { display:none; } It makes the content inaccessible. You want screen-readers to see your content, and visually style it by replacing the text with an image (like a logo). By using text-indent: -999px; or a similar method, the text is still there — just not visually there. Use display:none, and the text is gone.

Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58
jensimmons
  • 69
  • 1
  • 2
6
<style>
body {
     visibility:hidden
}
body .moz-signature p{
    visibility:visible
}
</style>

The above works well in latest Thunderbird also.

kamalesh
  • 61
  • 1
  • 1
  • Note that using this method makes the text un-readable to most screen readers -- see http://stackoverflow.com/questions/1755656/displaynone-vs-visibilityhidden-vs-text-indent9999-how-screen-reader-behave-w – Jordan Lev Nov 09 '11 at 03:26
5

Why don't you use:

<li><a href="#">bla</a></li>

a {
    opacity: 0.0;
    font-size: 1px;
}

li {
    background-image: url('test.jpg');
}

If you haven't any span or div element, it works perfectly for links.

franzlorenzon
  • 5,845
  • 6
  • 36
  • 58
Hans
  • 51
  • 1
  • 1
5

I don't recall where I picked this up, but have been using it successfully for ages.

  =hide-text()
    font: 0/0 a
    text-shadow: none
    color: transparent

My mixin is in sass however you can use it any way you see fit. For good measure I generally keep a .hidden class somewhere in my project to attach to elements to avoid duplication.

Jack Keller
  • 59
  • 1
  • 2
  • I think I've read somewhere that this version is prefered because a negative text-indent will cause the browser to render a 10000px (or whatever example you use) long box. Changing the font as in this example won't cause the browser to create a large box that it tries to render. – Gambo Jun 02 '19 at 08:14
5

repalce content with the CSS

 h1{  font-size: 0px;}
 h1:after {
    content: "new content";
    font-size: 15px;
  }
Hossein Hajizadeh
  • 1,357
  • 19
  • 10
5

The answer is to create a span with the property

{display:none;}

You can find an example at this site

Andrei Krotkov
  • 5,556
  • 3
  • 33
  • 36
  • 1
    Some of the downvotes probably have to do with accessibility concerns -- a valid point. But in my case, I'm pulling a menu from a restaurant menu service into a website via their web service. The restaurant owner doesn't want the prices displayed (but the same service is used to print the actual menus.) That's a situation where one doesn't want the prices on the site at all. It's good to know all the possible approaches. – Marvo Sep 08 '15 at 06:05
  • Downvotes have to do with this missing the question altogether. This completely hides the element, it does not however hide only the text of the element. – cchamberlain Mar 30 '21 at 22:19
5

you can use the css background-image property and z-index to ensure the image stays in front of the text.

Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58
Jobo
  • 940
  • 6
  • 11
4

This is actually an area ripe for discussion, with many subtle techniques available. It is important that you select/develop a technique that meets your needs including: screen readers, images/css/scripting on/off combinations, seo, etc.

Here are some good resources to get started down the road of standardista image replacement techniques:

http://faq.css-standards.org/Image_Replacement

http://www.alistapart.com/articles/fir

http://veerle.duoh.com/blog/links/#l-10

willoller
  • 7,106
  • 1
  • 35
  • 63
4

Content replacement is directly available in CSS by using the content property.

This seems to be most commonly used to generate ::before and ::after pseudo-elements, but can also be used to replace the content of existing HTML elements.

For the original example

<h1>My Website Title Here</h1>

this is the CSS that will replace the text with the logo:

        h1 {
            content: url(mywebsitelogo.png);
            width: 100%;
        }

While in pseudo-elements, any image content cannot be resized (except by using it as a background image), this is not the case for replaced content.

By default, the image will appear at its actual size, expanding the container if necessary, exactly as if it contained an actual <img> element.

In this example, width: 100% is used to fit the logo image to the full width. If the image should be shrink to fit, if needed, but never expanded if the container is larger than the image, then max-width: 100% can be used instead.

According to MDN, the only regular browser which does not support CSS content replacement is Internet Explorer.

WebSmithery
  • 1,060
  • 1
  • 8
  • 5
  • 1
    This really should be more popular. This is 100% the correct answer. I had no idea you could do this, and the support for modern browsers is there: https://caniuse.com/mdn-css_properties_content_element_replacement – Kyle Mar 06 '22 at 17:41
  • I can't seem to get this to work on elements, only pseudoelements: so `h1 { content: "new text";` doesn't work, but `h1::after { content: "new text"; }` does work. This is in Chrome 114. – Dai Jun 27 '23 at 01:02
  • UPDATE: So `content: url("someImage")` works on all elements, but `content: "text";` only works on psuedoelements. Weird... – Dai Jun 27 '23 at 01:05
3

Use Condition tag for different browser and using css you have to place height:0px and width:0px also you have to place font-size:0px.

Umesh Aawte
  • 4,590
  • 7
  • 41
  • 51
kedar
  • 31
  • 1
3

If the point is simply to make the text inside the element invisible, set the color attribute to have 0 opacity using a rgba value such as color:rgba(0,0,0,0); clean and simple.

Cafe Coder
  • 944
  • 9
  • 14
2

Try this code to shorten and hide text

.hidetxt{

  width: 346px;
  display: table-caption;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: no-drop;
  
}

.hidetxt:hover { 

  visibility: hidden;
  
}
<div class="hidetxt">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when</p>
</div>

or to hide use in your css class .hidetxt { visibility: hidden; }

omar kerr
  • 21
  • 2
2

One of the ways I achieve this is to use :before or :after. I've used this approach for several years, and particularly works great with glyph vector icons.

h1 {
    position: relative;
    text-indent: -9999px;                 /* sends the text off-screen */
    }
h1:before {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    display: block;
    width: 600px;
    height: 100px;
    content: ' ';
    background: transparent url(/the_img.png) 0 0 no-repeat;
    }
Pegues
  • 1,693
  • 2
  • 21
  • 38
2
h1 {
    text-indent: -3000px; 
    line-height: 3000px;
    background-image: url(/LOGO.png);
    height: 100px; width:  600px;  /* height and width are a must */

}
Georgi Nikolov
  • 1,155
  • 1
  • 11
  • 15
1

If we can edit the markup, life can be easier, just remove text and be happy. But sometimes the markup was placed by JS code or we just aren't allowed to edit it at all, too bad css turned to be the only weapon placed at our disposal.

We cannot place a <span> wrapping the text and hide the whole tag. By the way, some browsers do not only hides elements with display:none but also disables the components inside.

Both font-size:0px and color:transparent may be good solutions, but some browsers don't understand them. We can't rely on them.

I suggest:

h1 {
  background-image: url(/LOGO.png);  /* Our image */
  text-indent: -3000px;  /* Send text out of viewable area */
  height: 100px; width: 600px;  /* height and width are a must, agree */
  overflow:hidden;  /* make sure our size is respected */
}

Using overflow:hidden enforces our width & height. Some browsers (will not name them... IE) may read width and height as min-width and min-height. I want to prevent box to be enlarged.

ASR
  • 1,801
  • 5
  • 25
  • 33
Francisco
  • 11
  • 1
1

I usually use:

span.hide
{
  position:fixed;
  right:-5000px;
}
Anze
  • 119
  • 2
  • 9
1

Using zero value for font-size and line-height in the element does the trick for me:

<style>
    .text {
        display: block;
        width: 200px;
        height: 200px;

        font-size: 0;
        line-height: 0;
    }
</style>

<span class="text">
    Invisible Text
</span>
HelpNeeder
  • 6,383
  • 24
  • 91
  • 155
1

To hide text from html use text-indent property in css

.classname {
 text-indent: -9999px;
 white-space: nowrap; 
}

/* for dynamic text you need to add white-space, so your applied css will not disturb. nowrap means text will never wrap to the next line, the text continues on the same line until a <br> tag is encountered

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
0

This worked for me with span (knockout validation).

<span class="validationMessage">This field is required.</span>

.validationMessage {
    background-image: url('images/exclamation.png');
    background-repeat: no-repeat;
    margin-left: 5px;
    width: 16px;
    height: 16px;
    vertical-align: top;

    /* Hide the text. */
    display: inline-block;
    overflow: hidden;
    font-size: 0px;
}
Karson
  • 449
  • 6
  • 11
0

A solution that works for me :

HTML

<div class="website_title"><span>My Website Title Here</span></div>

CSS

.website_title {
    background-image: url('../images/home.png');
    background-repeat: no-repeat;
    height: 18px;
    width: 16px;
}

.website_title span {
    visibility: hidden;
}
Sébastien Gicquel
  • 4,227
  • 7
  • 54
  • 84
-1

The best answer works for short text, but if the text wraps it just shows up in the image.

One way to do it is catch errors with a jquery handler. Try to load an image, if it fails it throws an error.

$('#logo img').error(function(){
    $('#logo').html('<h1>My Website Title Here</h1>');
});

See SAMPLE CODE

Shanimal
  • 11,517
  • 7
  • 63
  • 76
-1
h1{
   background:url("../images/logo.png") no-repeat;
   height:180px;
   width:200px;
   display:inline-block;
   font-size:0px !important;
   text-intent:-9999999px !important;
   color:transparent !important;
 }
Harden Rahul
  • 930
  • 8
  • 15
  • 3
    While this code may answer the question, providing additional context regarding *why* and/or *how* this code answers the question improves its long-term value. – Benjamin W. Mar 16 '16 at 06:25