[css] Replacing H1 text with a logo image: best method for SEO and accessibility?

It seems like there are a few different techniques out there, so I was hoping to get a "definitive" answer on this...

On a website, it's common practice to create a logo that links to the homepage. I want to do the same, while best optimizing for search engines, screen readers, IE 6+, and browsers who have disabled CSS and/or images.

Example One: Doesn't use an h1 tag. Not as good for SEO, right?

<div id="logo">
    <a href="">
        <img src="logo.png" alt="Stack Overflow" />
    </a>
</div>

Example Two: Found this somewhere. The CSS seems a little hacky.

<h1 id="logo">
    <a href="">Stack Overflow</a>
</h1>
/* css */
#logo {
    padding: 70px 0 0 0;
    overflow: hidden;
    background-image: url("logo.png");
    background-repeat: no-repeat;
    height: 0px !important;
    height /**/:70px;
}

Example Three: Same HTML, different approach using text-indent. This is the "Phark" approach to image replacement.

<h1 id="logo">
    <a href="">Stack Overflow</a>
</h1>
/* css */
#logo {
    background: transparent url("logo.png") no-repeat scroll 0% 0%;
    width: 250px;
    height: 70px;
    text-indent: -3333px;
    border: 0;
    margin: 0;
}

#logo a {
    display: block;
    width: 280px; /* larger than actual image? */
    height: 120px;
    text-decoration: none;
    border: 0;
}

Example Four: The Leahy-Langridge-Jefferies method. Displays when images and/or css is turned off.

<h1 id="logo" class="logo">
    <a href="">Stack Overflow</a>
</h1>
/* css */
h1.logo {
    margin-top: 15px; /* for this particular site, set this as you like */
    position: relative; /* allows child element to be placed positioned wrt this one */
    overflow:hidden; /* don’t let content leak beyond the header - not needed as height of anchor will cover whole header */
    padding: 0; /* needed to counter the reset/default styles */
}

h1.logo a {
    position: absolute; /* defaults to top:0, left:0 and so these can be left out */
    height: 0; /* hiding text, prevent it peaking out */
    width: 100%; /* 686px; fill the parent element */
    background-position: left top;
    background-repeat: no-repeat;
}

h1#logo {
    height: 60px; /* height of replacement image */
}

h1#logo a {
    padding-top: 60px; /* height of the replacement image */
    background-image: url("logo.png"); /* the replacement image */
}

What method is the best for this sort of thing? Please provide html and css in your answer.

This question is related to css xhtml image seo

The answer is


After reading through the above solutions, I used a CSS Grid solution.

  1. Create a div containing the h1 text and the image.
  2. Position the two items in the same cell and make them both relatively positioned.
  3. Use the old zeldman.com technique to hide the text using text-indent, white-space, and overflow properties.
<div class="title-stack">
    <h1 class="title-stack__title">StackOverflow</h1>
    <a href="#" class="title-stack__logo">
        <img src="/images/stack-overflow.png" alt="Stack Overflow">
    </a>
</div>
.title-stack {
    display: grid;
}
.title-stack__title, .title-stack__logo {
    grid-area: 1/1/1/1;
    position: relative;
}
.title-stack__title {
    z-index: 0;
    text-indent: 100%;
    white-space: nowrap;
    overflow: hidden;
}

If accessibility reasons is important then use the first variant (when customer want to see image without styles)

<div id="logo">
    <a href="">
        <img src="logo.png" alt="Stack Overflow" />
    </a>
</div>

No need to conform imaginary SEO requirements, because the HTML code above has correct structure and only you should decide does this suitable for you visitors.

Also you can use the variant with less HTML code

<h1 id="logo">
  <a href=""><span>Stack Overflow</span></a>
</h1>
/* position code, it may be absolute position or normal - depends on other parts of your site */
#logo {
  ...
}

#logo a {
   display:block;
   width: actual_image_width;
   height: actual_image_height;
   background: url(image.png) no-repeat left top;
}

/* for accessibility reasons - without styles variant*/
#logo a span {display: none}

Please note that I have removed all other CSS styles and hacks because they didn't correspond to the task. They may be usefull in particular cases only.


Chiming in a bit late here, but couldn't resist.

You're question is half-flawed. Let me explain:

The first half of your question, on image replacement, is a valid question, and my opinion is that for a logo, a simple image; an alt attribute; and CSS for its positioning are sufficient.

The second half of your question, on the "SEO value" of the H1 for a logo is the wrong approach to deciding on which elements to use for different types of content.

A logo isn't a primary heading, or even a heading at all, and using the H1 element to markup the logo on each page of your site will do (slightly) more harm than good for your rankings. Semantically, headings (H1 - H6) are appropriate for, well, just that: headings and subheadings for content.

In HTML5, more than one heading is allowed per page, but a logo isn't deserving of one of them. Your logo, which might be a fuzzy green widget and some text is in an image off to the side of the header for a reason - it's sort of a "stamp", not a hierarchical element to structure your content. The first (whether you use more depends on your heading hierarchy) H1 of each page of your site should headline its subject matter. The main primary heading of your index page might be 'The Best Source For Fuzzy Green Widgets in NYC'. The primary heading on another page might be 'Shipping Details for Our Fuzzy Widgets'. On another page, it may be 'About Bert's Fuzzy Widgets Inc.'. You get the idea.

Side note: As incredible as it sounds, don't look at the source of Google-owned web properties for examples of correct markup. This is a whole post unto itself.

To get the most "SEO value" out HTML and its elements, take a look at the HTML5 specs, and make make markup decisions based on (HTML) semantics and value to users before search engines, and you'll have better success with your SEO.


I do it mostly like the one above, but for accessibility reasons, I need to support the possibility of images being disabled in the browser. So, rather than indent the text from the link off the page, I cover it by absolutely positioning the <span> to the full width and height of the <a> and using z-index to place it above the link text in the stacking order.

The price is one empty <span>, but I'm willing to have it there for something as important as an <h1>.

<h1 id="logo">
  <a href="">Stack Overflow<span></span></a>
</h1>
#logo a {
   position:relative;
   display:block;
   width:[image width];
   height:[image height]; }

#logo a span {
   display:block;
   position:absolute;
   width:100%;
   height:100%;
   background:#ffffff url(image.png) no-repeat left top;
   z-index:100; /* Places <span> on top of <a> text */  }

<div class="logo">
    <h1><a href="index.html"><span>Insert Website Name</span></a></h1>
    <p>Insert Slogan Here</p>
</div>
#header .logo h1 {
    background: red; /* replace with image of logo */
    display:block;
    height:40px; /* image height */
    width:220px; /* image width */
}

#header .logo h1 a {
    display:block;
    height:40px; /* image height */
    width:220px; /* image width */
}

#header .logo h1 a span {
    display:none;
}

<h1><a href="/" title="Some title">Name</a></h1>
h1 a{
  width: {logo width};
  height: {logo height};
  display:block;
  text-indent:-9999px;
  background:url({ logo url});
}

How W3C does?

Simply have a look a look at https://www.w3.org/. The image has a z-index:1, the text is here but behind because of the z-index:0 coupled to the position: absolute;

The original HTML:

<h1 class="logo">
    <a tabindex="2" accesskey="1" href="/">
        <img src="/2008/site/images/logo-w3c-mobile-lg" width="90" height="53" alt="W3C">
    </a>
    <span class="alt-logo">W3C</span>
</h1>

The original CSS:

#w3c_mast h1 a {
    display: block;
    float: left;
    background: url(../images/logo-w3c-screen-lg) no-repeat top left;
    width: 100%;
    height: 107px;
    position: relative;
    z-index: 1;
}
.alt-logo {
    display: block;
    position: absolute;
    left: 20px;
    z-index: 0;
    background-color: #fff;
}

A new (Keller) method is supposed to improve speed over the -9999px method:

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

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


I don't know but this is the format have used...

<h1>
    <span id="site-logo" title="xxx" href="#" target="_self">
        <img src="http://www.xxx.com/images/xxx.png" alt="xxx" width="xxx" height="xxx" />
        <a style="display:none">
            <strong>xxx</strong>
        </a>
    </span>
</h1>

Simple and it has not done my site any harm as far as I can see. You could css it but I don't see it loading any faster.


<h1>
  <a href="http://stackoverflow.com">
  Stack Overflow<img src="logo.png" alt="Stack Overflow" />
  </a>
</h1>

This was the good option for SEO because SEO gives the H1 tag high priority, inside the h1 tag should be your site name. Using this method if you search the site name in SEO it will show your site logo as well.

you want to hide the site name OR text please use text-indent in negative value. ex

h1 a {
 text-indent: -99999px;
}

One point no one has touched on is the fact that the h1 attribute should be specific to every page and using the site logo will effectively replicate the H1 on every page of the site.

I like to use a z index hidden h1 for each page as the best SEO h1 is often not the best for sales or aesthetic value.


I think you'd be interested in the H1 debate. It's a debate about whether to use the h1 element for the page's title or for the logo.

Personally I'd go with your first suggestion, something along these lines:

<div id="header">
    <a href="http://example.com/"><img src="images/logo.png" id="site-logo" alt="MyCorp" /></a>
</div>

<!-- or alternatively (with css in a stylesheet ofc-->
<div id="header">
    <div id="logo" style="background: url('logo.png'); display: block; 
        float: left; width: 100px; height: 50px;">
        <a href="#" style="display: block; height: 50px; width: 100px;">
            <span style="visibility: hidden;">Homepage</span>
        </a>
    </div>
    <!-- with css in a stylesheet: -->
    <div id="logo"><a href="#"><span>Homepage</span></a></div>
</div>


<div id="body">
    <h1>About Us</h1>
    <p>MyCorp has been dealing in narcotics for over nine-thousand years...</p>
</div>

Of course this depends on whether your design uses page titles but this is my stance on this issue.


You missed title in <a> element.

<h1 id="logo">
  <a href="#" title="..."><span>Stack Overflow</span></a>
</h1>

I suggest to put title in <a> element because client would want to know what is the meaning of that image. Because you have set text-indent for the test of <h1> so, that front end user could get information of main logo while they hover on logo.


For SEO reason:

<div itemscope itemtype="https://schema.org/Organization">
 <p id="logo"><a href="/"><span itemprop="Brand">Your business</span> <span class="icon fa-stg"></span> - <span itemprop="makesOffer">sell staff</span></a></p>
 </div>
   <h1>Your awesome title</h1>

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to xhtml

How to refresh table contents in div using jquery/ajax Uses for the '&quot;' entity in HTML The entity name must immediately follow the '&' in the entity reference Can I save input from form to .txt in HTML, using JAVASCRIPT/jQuery, and then use it? How to vertically align a html radio button to it's label? Image height and width not working? Removing border from table cells Enable & Disable a Div and its elements in Javascript how to remove the bold from a headline? How to make div occupy remaining height?

Examples related to image

Reading images in python Numpy Resize/Rescale Image Convert np.array of type float64 to type uint8 scaling values Extract a page from a pdf as a jpeg How do I stretch an image to fit the whole background (100% height x 100% width) in Flutter? Angular 4 img src is not found How to make a movie out of images in python Load local images in React.js How to install "ifconfig" command in my ubuntu docker image? How do I display local image in markdown?

Examples related to seo

Can a relative sitemap url be used in a robots.txt? How do search engines deal with AngularJS applications? What is the purpose of the "role" attribute in HTML? How to request Google to re-crawl my website? When should I use a trailing slash in my URL? Redirecting 404 error with .htaccess via 301 for SEO etc .htaccess 301 redirect of single page Replacing H1 text with a logo image: best method for SEO and accessibility?