惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
AI
AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Hacker News: Front Page
P
Proofpoint News Feed
Know Your Adversary
Know Your Adversary
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Hacker News
The Hacker News
腾讯CDC
O
OpenAI News
Vercel News
Vercel News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
量子位
S
Schneier on Security
T
Tor Project blog
B
Blog
The Register - Security
The Register - Security
宝玉的分享
宝玉的分享
S
Securelist
有赞技术团队
有赞技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
G
GRAHAM CLULEY
Hugging Face - Blog
Hugging Face - Blog
W
WeLiveSecurity
D
DataBreaches.Net
TaoSecurity Blog
TaoSecurity Blog
博客园 - Franky
Latest news
Latest news
I
Intezer
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
PCI Perspectives
PCI Perspectives
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
GbyAI
GbyAI
F
Full Disclosure
V
V2EX
Project Zero
Project Zero
The Last Watchdog
The Last Watchdog
T
Tenable Blog
Security Latest
Security Latest
Attack and Defense Labs
Attack and Defense Labs
F
Fortinet All Blogs
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint

CSS Wizardry

Front-End’s Missing Metric: The TBT Window Meet Your Users Where They Are with Obs.js Better Browser Caching with No-Vary-Search font-family Doesn’t Fall Back the Way You Think What Is CSS Containment and How Can I Use It? When All You Can Do Is All or Nothing, Do Nothing Obs.js: Context-Aware Web Performance for Everyone Low- and Mid-Tier Mobile for the Real World (2025) The Fastest Site in the Tour de France Making Sense of the Performance Extensibility API Why Do We Have a Cache-Control Request Header? HTML Is Not a Programming Language… Build for the Web, Build on the Web, Build with the Web Licensing Code on CSS Wizardry A Layered Approach to Speculation Rules Designing (and Evolving) a New Web Performance Score Core Web Vitals Colours The Ultimate Contract Templates for Tech Consultants: Protect Your Business and Get Paid Optimising for High Latency Environments Cache Grab: How Much Are You Leaving on the Table? blocking=render: Why would you do that?! Correctly Configure (Pre) Connections The Three Cs: 🤝 Concatenate, 🗜️ Compress, 🗳️ Cache What Is the Maximum max-age? How to Clear Cache and Cookies on a Customer’s Device The Ultimate Low-Quality Image Placeholder Technique Core Web Vitals for Search Engine Optimisation: What Do We Need to Know? The HTTP/1-liness of HTTP/2 In Defence of DOM­Content­Loaded Site-Speed Topography Remapped Why Not document.write()? Speeding Up Async Snippets Critical CSS? Not So Fast! Measure What You Impact, Not What You Influence Optimising Largest Contentful Paint Measuring Web Performance in Mobile Safari Site-Speed Topography Speed Up Google Fonts Real-World Effectiveness of Brotli Performance Budgets, Pragmatically Lazy Pre-Browsing with Prefetch Making Cloud.typography Fast(er) Time to First Byte: What It Is and How to Improve It Self-Host Your Static Assets Tips for Technical Interviews Cache-Control for Civilians Bandwidth or Latency: When to Optimise for Which ITCSS × Skillshare What If? CSS and Network Performance The Three Types of Performance Testing Getting to Know a Legacy Codebase Image Inconsistencies: How and When Browsers Download Images Identifying, Auditing, and Discussing Third Parties My Digital Music Setup Measuring the Hard-to-Measure Finding Dead CSS The Fallacies of Distributed Computing (Applied to Front-End Performance) Ten Years Old Relative Requirements Airplanes and Ashtrays Performance and Resilience: Stress-Testing Third Parties Refactoring Tunnels Little Things I Like to Do with Git Writing Tidy Code Configuring Git and Vim Base64 Encoding & Performance, Part 2: Gathering Data Base64 Encoding & Performance, Part 1: What’s Up with Base64? Code Smells in CSS Revisited Typography for Developers Moving CSS Wizardry onto HTTPS and HTTP/2 Ack for CSS Developers A New Year, a New Focus Preparing Vim for Apple’s Touch Bar Choosing the Correct Average CSS Shorthand Syntax Considered an Anti-Pattern CSS Wizardry Newsletter Nesting Your BEM? Improving Perceived Performance with Multiple Background Images Continue Normalising Your CSS Pure CSS Content Filter Pragmatic, Practical, and Progressive Theming with Custom Properties Refactoring CSS: The Three I’s Speaker’s Checklist: Before and After Your Talk Improving Your CSS with Parker The Importance of !important: Forcing Immutability in CSS Mixins Better for Performance Managing Typography on Large Apps White October Events Workshop Partnership BEMIT: Taking the BEM Naming Convention a Step Further Travelling Like You Want to, When You Have To Contextual Styling: UI Components, Nesting, and Implementation Detail Subtleties with Self-Chained Classes Cyclomatic Complexity: Logic in CSS Immutable CSS Can CSS Be Too Modular? More Transparent UI Code with Namespaces When to use @extend; when to use a mixin The Specificity Graph CSS Wizardry Ltd.: Year 1 in review
Annotated <figure>s in HTML5 and CSS
Harry Roberts · 2011-06-04 · via CSS Wizardry

Written by on CSS Wizardry.

Table of Contents

Independent writing is brought to you via my wonderful Supporters.

  1. Demo
  2. The code
    1. The HTML
    2. The CSS
    3. A couple of things to note

I’ve never really been one for CSS experiments. They’re cool and all, but I prefer solving real problems with good ol’ CSS and markup. This is what this next thing was born from and I’m really pleased with the outcome! It’s image maps, meet annotations, meet HTML5’s <figure> element.

Basically, we all know HTML5 has given us some pretty awesome new elements to toy with and some of the more humble ones are <figure> and <figcaption>:

<figure>
     <img src="/img.jpg" alt="">
    <figcaption>Caption for above image</figcaption>
</figure>

In this post I’ll show you how to turn that into an image-map style annotated image using really really semantic markup.


Demo

You’re probably familiar with Flickr’s notes which are shown upon hovering an image. Well functionally this is exactly like that (I’ve never actually looked at their markup but I imagine it’s nigh on identical). Where this differs is that it uses some super-rich and semantic markup and it can be used as a CSS plugin! Simply paste the CSS into your site’s stylesheet and start using HTML5 <figure> annotations.

The code

This technique is a really good example of layers of code. Perfect HTML that works absolutely great on its own, totally semantic and well structured. It doesn’t need the CSS at all to function, the CSS just enhances it.

The HTML

The HTML is lovely and simple. Before we go any further go back to the demo page and disable styles. Seeing this without styles should show you just how semantic and sensible the markup really is. It’s a perfect HTML layer that doesn’t even need CSS to make sense or work.

I’ve not included the whole page as all we really want to look at is this:

<figure class="annotated">

  <img src="img/photo.jpg" alt="Photograph of me on my bike" />
  
  <figcaption>
  
    <b>Things to note:</b>
    
    <ul>
      <!-- Positions of the list-items. These need defining inline. -->
      <li style="top:255px; left:150px;">Helmet.</li>
      <li style="top:420px; left:140px;">Ruptured ligaments in my ankle.</li>
      <li style="top:480px; left:130px;">Low pressures.</li>
      <li style="top:390px; left:325px;">The trailer I just jumped from.</li>
    </ul>
    
    <i><a href="http://www.flickr.com/photos/suzannahaworth/4707464578/">Photo</a> by <a href="http://twitter.com/suzehaworth">@suzehaworth</a>.</i>
    
  </figcaption>
  
</figure>

All we have here is a <figure> and <figcaption> with an image, a title and a list. The image is the subject of our figure and the list makes points about it. To associate these points with the image we simply have a <b> which we use to textually make the connection.

The CSS

/*------------------------------------*\
  ANNOTATIONS
\*------------------------------------*/
/*
Apply a class of annotated to any figure you would like, well, annotated!
*/
.annotated{
  position:relative;
  /*display:inline-block; If you do not need to support IE7 and below uncomment this line and remove the inline width and height styles on the <figure> in your markup. */
}
.annotated img{ /* Set this to stop white-space appearing under the image. */
  display:block;
}
.annotated b{ /* Hide the figcaption’s title. */
  position:absolute;
  left:-99999px;
}
.annotated ul{ /* Set up the canvas for the annotations to sit on. */
  list-style:none;
  position:absolute; 
  top:0;
  right:0;
  bottom:0;
  left:0;
}
.annotated li{
  display:block;
  padding:0 5px;
  /* Give them a width and a line-height suitable for your kind of images. I chose 50px. */
  width:40px; /* 40px + 5px padding-right  + 5px padding-left = 50px */
  line-height:50px;
  position:absolute;
  text-indent:-99999px; /* Hide the text off-screen. */
  white-space:nowrap; /* Stop the annotations breaking onto several lines. */
  cursor:default;
}
.annotated:hover li{ /* When we hover the figure show us where the annotations are. */
  border:1px solid #fff;
}
.annotated li:hover { /* Show the text on hover. */
  background:#fff;
  background:rgba(255,255,255,0.75);
  z-index:2; /* Bring current annotation above others. */
  /* Remove the width and text-indent to show us our text! */
  width:auto;
  text-indent:0;
  
  /* A bit o’ progressive enhancement */
  -webkit-box-shadow:0 0 5px rgba(0,0,0,0.25);
     -moz-box-shadow:0 0 5px rgba(0,0,0,0.25);
         box-shadow:0 0 5px rgba(0,0,0,0.25);
}

The CSS is fairly well commented but basically what we do is:

  • Hide the <b> title.
  • Absolutely position and stretch the <ul> over the image.
  • Give the <li>s a width and (line-)height and hide the text off-screen.
  • Add borders to the list items when we hover the <figure>.
  • Remove the width from and give a border to the <li>s on hover, and reveal the text.

A couple of things to note

Firstly, the list items need positioning with inline styles in the markup. This is far more pragmatic than giving each <li> an ID and doing each one through an external CSS file.

Secondly, and more in depth, how do we get the the <figure> to wrap around and hug the image? We have four options.

  • Leave it as-is, like I have here. This means that if you hover to the right of the image you are technically still inside the (block-level) <figure> and this will display the list item borders when your cursor isn’t actually over the image. This isn’t too bad, but a little unexpected…
  • Float the <figure> left, which will force it to hug up to its largest child. The problem here is that you would have to clear:both; the subsequent element.
  • Give the <figure> display:inline-block;, but this won’t work in IE7 and below.
  • The final and, in my opinion, most pragmatic solution would be to simply add an inline width and height to the <figure> which is identical to the dimensions of your image, thus: <figure style="width:427px;height:640px;">.

Decide which of those will suit your project best and put it to work. Simply pasting the CSS into your stylesheet and obeying the markup structure will allow you to annotate your figures in a much nicer fashion.

I have just put this on GitHub in a CSS plugin type fashion. Please feel free to download and poke through the code.