Forum posts are generally marked up using tables. This is not the correct choice from an accessibility point of view. Tables force screen readers first to serialize table data and then to navigate such data in a way that is not predictable. In fact, establishing the correct relationships between table elements is not so easy as it could seem. For example, how we should mark up the author of a post using a table element? And what is the correct element to use for a post title? Using WAI-ARIA roles would allow us to give semantic roles to each table element, but at the moment of this writing, WAI-ARIA roles are not widely supported, so our natural choice remains HTML and CSS. Let's see how to accomplish this.
The markup
A possible markup choice for our forum posts would be the following:
<div class="message"> <div class="message-header"> <h2>...</h2> </div> <div class="message-author"> <p><a href="#">..</a></p> <img src="1.jpg" alt="Author's avatar" /> </div> <div class="message-body"> ... </div> <div class="message-replies"> <h3>...</h3> <ul class="replies"> <li> <div class="reply-header"> <h4><a href="#">Author</a> wrote</h4> <img src="2.jpg" alt="Comment author's avatar" /> </div> <blockquote> ... </blockquote> </li> <!--more replies--> </ul> </div> </div>
To achieve the maximum flexibility, we use several CSS classes that can be applied consistently across forum pages. Our main container, having the class message
, can be further stylized by adding an ID to it. This ID will be automatically generated by the server-side language that handles our forum. If we apply a prefix to it, such as forum_msg_
, we could add more styles by using advanced CSS3 attribute selectors. For example:
div[id^="forum_msg_"] {...}
The CSS styles
From a pure CSS perspective, the difficult part to address here is the vertical positioning of the avatar images near to text. Sure, we could use floats to align the image with the next element, but this won't guarantee the correct vertical alignment. Instead, we can use contextual positioning to achieve this effect.
Our images are 64 x 64 JPEG images, so they're simple squares. We need a container with a stated height and position: relative
. Then our images should be vertically positioned using top: 50%
and a negative top margin equal to the half of their height, that is, 32 pixels.
First, our avatar in the message-author
section:
#content div.message-author { height: 84px; width: 60%; position: relative; margin: 0 auto; } #content div.message-author img { width: 64px; height: 64px; display: block; position: absolute; top: 50%; left: 0; margin-top: -32px; } #content div.message-author p { height: 100%; line-height: 84px; padding-left: 75px; font-size: 1.1em; }
The paragraph next to the image has a left padding that takes into account the width of the avatar image. This is due to the fact that now our image has been completely removed from the normal flow.
Just for the sake of this example, I've specified an height in pixels. This is not always a correct choice, because a user could change the text size and undesired overlaps may occur. To avoid this, you can specify an height in ems. Since our base font size is 12 pixels, then 84 divided by 12 is 7em. Using ems is always a good choice, especially when the container has a background color:
#content ul.replies li div.reply-header { background: #333; color: #fff; height: 80px; width: 100%; position: relative; line-height: 80px; text-align: center; } #content ul.replies li div.reply-header img { position: absolute; display: block; width: 64px; height: 64px; top: 50%; left: 5px; margin-top: -32px; }
In this case I've specified an height of 80 pixels, which is roughly equivalent to 6.6em, if we calculate this value according to our base font size. It's always preferable to use ems for element's height to avoid any possible problems when a user resizes the text.