How to choose your hotel room with CSS and JavaScript

I work for Hilton Hotels, which operates Homewood Suites. Homewood Suites has just rolled out a way to choose your hotel room (or in this case, “suite”) by selecting the room on a diagram of a floorplan. It’s driven by CSS and JavaScript, and this post will explain how the interface works.

Homewood Suites eCheck-in Process

Homewood Suites eCheck-in Process

The Demo

You can interact with the demo, which includes one floor and some sample rooms. You can choose and switch rooms using either the left side, which shows the traditional radio input choice list, or the right side, by selecting an available room on the map and clicking the “Switch to this suite now” link in the popup.

You may also download the demo in zip format, which includes all html, CSS, images, and JavaScript. (I’m posting this with the blessing of my employer, who is allowing me to share my code with professionals in my field for fun and education. You cannot use the images for your own purposes other than for educational ones, as this doesn’t really belong to me, but to Homewood Suites.)

A note about accessibility

This is the part where you would read that users who have JS and CSS disabled were my highest consideration, but they weren’t. My priority was to get this thing working. However, just by the nature of separating structure, presentation, and behavior, graceful degradation can sometimes just happen. Turn off CSS and/or JavaScript, and you’ll see that guests can still complete the form. Frankly, that was enough for my part. In the case of no CSS, there is a bit of a mess following the submit button, but it’s an acceptable mess, and much of it will likely not make it to the production version (since most of it is unselectable rooms, which our database will likely not return). Also, the idea is that, on the page before this, there is a javascript check, and the guests is sent to a non-floorplan version to choose their room if JavaScript is disabled.

Let’s begin

You know those “escape route” plans that are taped to the back of a hotel door? If you create one of those in digital format without the arrows that point to the exit, you’ll have our starting point: a single hotel floor.

Floor 2

Note that room numbers, exits, compass direction, and locations of elevators/vending etc. are all part of the image, since they are static. Since available rooms are dynamic, those will be layered on top of the floorplan using CSS positioning.

First, we create a div where the plan will sit.

<div id="plan">
  <!-- no content yet --> 

…and style it to hold the floorplan image:

#plan {
  width:231px; /* background image width */
  height:700px; /* background image height */
  background:#fff url(../images/floorplan.gif) no-repeat 50% 50%;
  border:1px solid #666;
  position:relative; /* this is key! */

The rooms will be represented with <a> tags, and will be absolutely positioned on the map. For this reason, the #plan div is set to “position:relative;”, so that once the rooms’ <a> tags are positioned, they will be in relation to the #plan div instead of the top left corner of the browser window.

Add Some Rooms

As stated, rooms are represented with the <a> tag. The href value leads nowhere, the id pinpoints the room itself (I couldn’t use the room number here because id has to start with a letter), and I used the rel attribute to contain the actual room number.

<div id="plan">
  <a href="#" id="a01" rel="201"></a>
  <a href="#" id="a02" rel="202"></a>
  <a href="#" id="a03" rel="203"></a>
  <a href="#" id="a22" rel="222"></a>
#plan a {

By default, every room on the floor is listed in the html, and set to display:none; in the CSS. The idea was that only selectable rooms would have a class that set them to display:block;. In the final version, I believe any room that wouldn’t have been selectable wouldn’t be in the html.

The rooms are positioned in the CSS.

#plan a#a01	{top:126px;left:148px;}
#plan a#a03	{top:167px;left:148px;}
#plan a#a05	{top:208px;left:148px;}
#plan a#a07	{top:250px;left:148px;}
#plan a#a09	{top:289px;left:148px;}
#plan a#a11	{top:331px;left:148px;}

For rooms that are available, they are set with class=”avail”. If room 204 was available for a guest to choose, the html would appear like so:

<div id="plan">
  <a href="#" id="a03" rel="203"></a>
  <a href="#" id="a04" rel="204" class="avail"></a>
  <a href="#" id="a05" rel="205"></a>

And if JavaScript is enabled on the browser, a function runs that attaches display:block; to that room. (If JavaScript is not enabled, guests can still refer to the map while choosing their room with a radio choice.)

function makeAvailableRoomsViewable() {
  var plan = document.getElementById("plan");
  var rooms = plan.getElementsByTagName("a");
  for (var i=0;i<rooms.length;i++) {
    if (rooms[i].className == "avail") {
      rooms[i].style.display = "block";

I’m using a little orange icon to indicate the room is selectable. So I make sure to style it accordingly.

#plan a.avail {
  background:transparent (../images/ico_avail.gif) no-repeat 50% 50%;

Available rooms are now indicated on the map with an yellow-orange rounded square.

Viewing Room Details

At this point, we could’ve set it up so that you just click this square to select that particular room, like a highly stylized radio input, but one of the requirements of the floorplan was to also be able to view more details about the room. So selecting the square enables a CSS popup. It’s coded similar to how Eric Meyer describes CSS popups, with a <span> within an <a>.

<a href="#" id="a04" rel="204" class="avail">
  <span class="pop">
  <!-- details about the room go here -->

In Meyer’s popups, the span is set to display:none; in the normal state, and switch to display:block; on hover of the parent <a>. Because we wanted guests to be able to read and select options within the popup, we opted for the popup to appear on mouse click instead of mouse hover. This way, the popup would not require the user to keep the mouse within certain dimensions in order to view it. However, whereas :hover-driven popup would’ve only required CSS, we needed to create some JavaScript to handle the onclick event.

Our JavaScript will, on mouse click, change the class of the <a> tag from “avail” to “availPop”. The “availPop” class is defined in CSS to assign display:block; to the interior span element.

function preparePops() {
  var plan = document.getElementById("plan");
  var rooms = plan.getElementsByTagName("a");
  for (i = 0; i < rooms.length; i++) {
    rooms[i].onclick = function() {
      if (this.className == "avail") {
        this.className = "availPop";
        return false;

Note the "clearPops()" function that runs before the class name is changed. That function cycles through all other rooms, and if any one of them already has its popup showing, the class name is changed and the popup is closed. (It checks to see if any other room already has a class of "availPop", and changes it to just "avail".) This way you're only viewing one popup at a time.

The CSS Popup

The main purpose of introducing this floorplan option when checking into the hotel was to allow guests to be able to choose a precise location of their room. An additional feature was the inclusion of the popup, which is the span that contains the room description, images, and a trigger to select the room.

The popup is just made up of many <span>s and a couple of <img> tags, which are styled and anchored for DOM manipulation.

<a href="#" id="a04" rel="204" class="avail">
  <span class="pop">
    <span class="roomNumber">Suite 204</span>
    <img class="closePop" src="images/ico_close.gif" alt="close" />
    <span class="status">Status: Available</span>
    <span class="statusYours">Status: Selected Suite</span>
    <span class="switchRoom">Change to this suite now</span>
    <span class="roomtypeimage"><img class="roomImg" src="images/roomtype01.jpg" alt="" />
    <span class="imgTypeDisclaim">Photo of Room Type: Not Actual Suite</span></span>
    <span class="imgCycle"><span class="imgprev"><img src="images/ico_imgPrev.gif" alt="Back" /></span><span class="roomImgCurrentNum">1</span> of <span class="totalImages">1</span><span class="imgnext"><img src="images/ico_imgNext.gif" alt="Next" /></span></span>
    <span class="details">This is a non-smoking suite.<br />Beds: King</span>

Depending on the class of the parent <a>, some items are set to display:none, while others, display:block.

Notice that the "Photo of Room Type: Not Actual Suite" is actually text, not part of the image itself. The text is just positioned over the image and given some opacity using CSS. Doing it this way allowed us to save space by including the message on the image itself, but we didn't have to edit all the images we already have on file for each room type. Since the wording changed a few times during the development process, keeping it as text (vs an image) made it an incalculably valuable time saver for updating.

Our databases already had more than one picture for some room types, and very basic slideshow was set up to accomodate it. I used very rudimentary JavaScript for this, which updates the src attribute of the image as the arrows below are clicked.

The "Selected" Room

Once a guest has chosen a room, it is differentiated from the other available rooms by the use of a blue rounded square as the background image.

I call that the "on" state. So how is that room chosen? There is a span within the CSS popup that I've styled to look like a link, which says "Change to this suite now".

If that span is clicked, the desired room's <a> tag's class name is switched to "on".

function changeRooms() {
  var plan = document.getElementById("plan");
  var rooms = plan.getElementsByTagName("a");
  for (i = 0; i < rooms.length; i++) {
    var spans = rooms[i].getElementsByTagName("span");
    for (j = 0; j < spans.length; j++) {
      if (spans[j].className == "switchRoom") {
        spans[j].onclick = function() {
          this.parentNode.parentNode.className = "on";

The CSS file has different styles for the "on" room so that it is obvious it is the guest's chosen selection.

In the JavaScript, note that before the class name for the desired room is switched to "on", a function called "turnOtherOnRoomsToAvail()" runs, which does exactly what it's title says. It goes through the rooms and changes whichever one is currently selected (class="on") back to available (or class="avail").

Radio button and floorplan room selection dependency

You'll also notice that another function called "selectTheRoomRadio()". As stated earlier, guests may choose their rooms using either the left-side radio input list, or the right-side floorplan. We want the left side to know what the right side is doing, and vice versa. For example, if I choose room 204 in the radio input list, then room 204 should switch to the "on" state in the floorplan (as indicated by the blue rounded square in the chosen room). Also, if I select "Change to this suite now" from the CSS popup on the floorplan for room 208, I want the radio input for room 208 to have a selected state.

Why is Homewood Suites doing this?

Hotels want to offer guests as much control over the room selection process as they can. Selection criteria that have already existed for Homewood Suites were traits like high/low floor, handicap accessibility, smoking preference, proximity to the elevator, etc. With this floorplan diagram, guests can now visualize exactly how close a room is to the elevators, exits, ice machine, etc., and even can see what direction their room is facing (in case they want to wake up to the sunrise versus enjoying a view of the sunset).

Conclusion and Notes of Interest

There is a little more to the code than what I described above - too much more for me to discuss in detail. If you view source of the demo, it should all be decipherable.

This floorplan application is not used for the reservation process, but instead for "eCheck-in", which allows guests to check in online a certain number of hours before their actual scheduled arrival to the hotel. Being new to the hotel industry, and not a frequent traveler, part of this project for me was an education on hotel reservation process. For example, making a reservation doesn't mean that a particular room number is assigned to the guest. The room number doesn't get assigned until closer to check-in time, if not during check-in itself. For this reason, the visual floorplan does not lend itself well to the reservation process, as choosing a room number at reservation time is not something the hotels are set up to do. So for now, this application would only be viewable for those guests choosing to check in online.

I was one of many hands that touched this project. If anything on the floorplan doesn't make sense (for instance, that statement about "Upgraded Suite", or the "Push to Talk" button), I understand, but know that there are reasons for their existence that fall beyond my purview.

It's also worth noting that the version that went into production is functionally better than the demo on this site, particularly when it comes to changing floors, which the demo doesn't show at all.

This article was ported from an older CMS, and comments were purposefully lost in the migration. If some were found most relevant, I pasted them to the bottom of that post. No new comments are accepted on these older articles.

Comments are closed.