OneCMS homepage relaunches

Project: Redesigns of the CIO, CSO, and Computerworld homepage and header (and later, InfoWorld and Network World) as part of adding international editions to IDG’ in-house CMS.

Date: 2018-2019

Involvement: I was one of two front-end developers working on this project. Based on comps from our UX team (Zach Sullivan and James Kocik) and requirements from product manager Galen Gruman, I architected the homepage and header markup that would be shared across all brands, and built out the CIO, CSO, and InfoWorld redesigns myself. My teammate Joan Joly implemented the design on Computerworld and Network World using the markup I had laid out, and also masterminded the JavaScript behind the “edition picker.” Back-end work was courtesy of Jim Hutson, Sagar Patade, and the Webnish team in India.

Description: In 2018 IDG made the decision to bring many of its international websites onto our in-house, custom-built CMS, which already powered most of the US brands. These international brands would no longer be standalone sites; instead they would be “editions” of their core brand. (So, for example, CIO Asia became CIO’s ASEAN edition). This was a project termed “OneCMS.”

As part of this, a redesign of many brands’ homepages and header/navigation was necessary, as they would now need to display different content based on the edition the user chose, and much of that content would need to be slotted in our CMS by non-technical users.

Additionally, we wanted to move away from the model whereby each IDG brand had its own homepage markup, even though much of the code was duplicated across brands. Instead we wanted a shared homepage, where we could use the same markup for each brand, but “theme” it using its own CSS.

I was the principal front-end resource for CIO, the first of the brands to undergo the OneCMS experiment. I used this as an opportunity to set the tone for the project front-end, architecting the core structure of the new homepage and navigation according to the principles of Don’t Repeat Yourself and Separation of Concerns. I wrote most of the new markup, using a mix of HTML and JSTL (the templating language used by Java Servlet Pages).

As mentioned, a good chunk of the individual branding was accomplished through the good ol’ fashioned CSS cascade. But there were some things we couldn’t reskin with CSS alone, such as text content. (For example, each site has a different name, tagline, and list of footer links; these would not differ by edition). My organizing principle for this content was to use each brand’s “properties” file — an XML file containing brand-specific information, such as tagline, links to the logo images, social media info, API keys, etc — for anything that could not be shared between sites. While updating the properties file did require a code release, this seemed acceptable for content that would not change often.

We built the new homepages in parts, so let me discuss each one individually:

The homepage nameplate and primary navigation on CIO.

Homepage nameplate: this sits above the primary navigation, displaying the brand’s logo and a coordinating background image, color, or color gradient. It is only displayed on the homepage, and not any inner pages of the site. It is also not displayed at the mobile breakpoint.

This was the first part of the new homepage I built, and I was still figuring out what I could handle in the CSS vs. what I needed the properties files for, so this is built such that the logo, background image, background color, and background gradient (optionally) are set in the properties files, and inserted into the page as JSTL variables. While the logo pretty much has to work this way, as it’s inserted as an <img> tag, the other properties could have been done with CSS alone. This is a change I would make if I had to refactor this, in the interest of not having to interpolate JSTL variables into a <style> tag (which breaks the principle of Separation of Concerns).

The logo also needed to be able to adjust to a range of browser widths without a loss in fidelity, so we used lossless SVG files and percent widths rather than static pixel values. Since the nameplate is not used on the mobile view of the site, we only load the large SVG at tablet widths or higher. (This is accomplished solely with CSS media queries; no JS is necessary).

Finally, the nameplate uses the relatively new position:sticky CSS declaration. This allows the primary navigation to appear to move over it as the page is scrolled.

Primary navigation:

The primary navigation on OneCMS brands sits between the homepage nameplate and the main content of the page when the page is loaded. As the user scrolls down the page, the nav covers the nameplate above it, and eventually fixes at the top of the viewport.

At desktop breakpoints, the primary navigation displays the site logo, the edition picker, Insider login/registration controls, a button to open the megamenu (see below), a button to expand the search window, and a menu of site- and edition-specific links. At tablet breakpoints, the links are dropped; at mobile breakpoints, only the logo, edition picker, and megamenu button remain.

The Insider controls are designed so that a logged-in user will see different content from a logged-out or unregistered user. This is done by setting an Insider cookie whenever a user logs in, which is read when the page is first loaded.


Top Stories:

Trending bar:

Top Stories Promo:

Editorial promos:

“Crawl” (Content List):

Sponsored Content Promo:

Resources module:

Ordering: Since the entire homepage is built using Flexbox, we are able to take advantage of the order property on Flexbox items in order to change the order of elements on the page without affecting their order in the DOM. This was useful because we wanted to allow editors to reorder content on the page.

While a great idea in theory, it worked less well in practice, due to a few concerns. One was that we lacked a UI for editors to change the order of elements on the page, and didn’t have the resources to build one out. So we had to resort to a raw HTML slotting module where they would actually have to tinker with the CSS to change the value of the order property. While every attempt was made to make this user-friendly, in the end the decision was made that we would hide the ordering slotting module from editors, only to be touched by Engineering and UX.

The second concern was simply that, if an order property is not explicitly set on a flex element, it defaults to zero. Elements with 0 weight are sorted by their order in the DOM. The only negative value for order with any meaning is -1; every other negative number is treated as a -1. This meant that either every element had to have an explicit order property, or it basically displayed in DOM order. Since the editors would be setting only the weight of individual elements — not every one on the page — this meant we had to set the order property explicitly in the codebase. Setting an order property for every element on the page in CSS was tedious, and ended up causing some unexpected results. (The order of the elements on the current websites is not entirely as designed!)

Technologies: Front-end: HTML, JSTL, CSS (including Flexbox), JavaScript, JQuery, responsive web design, micro-interactions/animations. Back-end: Java, JSP, Struts, running our custom in-house CMS.

Status: I no longer maintain this, but the sites are still live and using the same design and code, for now.


Project: Teamer: Make the Perfect Cuppa

Date: Summer 2020

Involvement: Wholly designed and developed by me.

Description: As a personal enrichment project, I decided to create a tea timing web application. This would allow you to select a type of tea (green, black, white, etc) which will automatically set a brewing time and display the brewing temperature. The user could then adjust the time up or down in increments of 10 seconds or 1 minute. An alarm plays when the timer is done.

Although simple to describe, the timing logic was not always easy to implement! Afterward, I wrote a more detailed post about what I learned about measuring time in JavaScript.

Technologies: HTML, CSS (including Flexbox), vanilla JavaScript. No images are used; just emoji, which are HTML entities. The tea buttons were created with a combination of border-radius:50% and the padding-top aspect ratio hack to maintain the same height and width despite Flexbox’s… flexiness.

Status: Live

Potential improvements:

  • Allow users the ability to add a tea, and store it using their local storage
  • Use Sass or Stylus for CSS
  • Visual effects – border that changes color? (per iOS timer)

Caveat: since I haven’t touched this since 2020, I’m unlikely to get to it any time soon!

Additional Notes: Right now this is deployed as flat files FTPed to hosting space. Might set up as a Netlify site (or similar) for build/deploy/hosting in the future, but probably not until I move my blog to a static site generator.


Project: InsiderPro

Date: August 2019

Involvement: I was the principal front-end developer on this project, as part of my role as a senior front-end developer at IDG. UX team member James Kocik designed the comp, according to the requirements of Mark Lewis, manager of IDG’s Insider products. As this was a clone of an existing site, minimal back-end work was required.

Description: InsiderPro is IDG’s first paid subscription site, and its design is modeled after other sites in IDG’s portfolio, i.e. CIO. Therefore most of my work was “theming” — adjusting the site styles on top of the base HTML that all such sites use.

The article gating, subscription offer, and login/account management functionality were implemented using third-party Piano’s Composer, VX, and ID tools, with some extra custom JavaScript on our end. The goal of total experience was to encourage users to sign up for a subscription plan, and to only allow them to read full articles if they had subscribed. The Piano experiences were piped into our site via iframes, and thus I also needed to work in Piano’s web interface in order to bring the HTML/CSS into line with InsiderPro’s branding.

Technologies: Front-end: HTML, CSS (including Flexbox), JavaScript, JQuery. Back-end: Java, JSP, Struts, running our custom in-house CMS. Third party: Piano’s Composer, VX, and ID tools.

Status: I no longer maintain this, but the site is still live and using the same design and code.


Project: GameStar site build for IDG

Date: 2017

Involvement: I was the principal front-end developer on the initial site build, as during my time as a senior front-end developer at IDG. James Kocik was responsible for UX and comp design for this site. The structure of the site is based off other sites in the IDG portfolio, eg. TechConnect. Mostly my work was on the homepage; the articles and category/tag index pages retained the look of other IDG sites. As a clone of an existing site, no back-end work was required.

Description: GameStar was created as IDG US’ first game-focused site, using a recognized brand name from IDG Germany. The design was based off the contemporaneous design of TechConnect (which no longer uses the same design).

The top of the page shows a typical three-article hero of featured content, slottable by IDG editors. The content list below it is populated in reverse chronological order. This “crawl,” as we termed it, uses CSS Flexbox to display 2-3 columns of equal height boxes. Each box presents the title, description, and primary image for that article; the primary image uses CSS cropping to display the images at a 3:2 aspect ratio, allowing them to maintain their native ratio but remain a consistent height.

An integrated ad unit is also included in the flexible design, as well as a sidebar with a list of recent “DealPosts” (affiliate revenue-generating posts).

Technologies: HTML, CSS (including Flexbox), JavaScript, JQuery. On the back-end, Java, JSP, Struts, running our custom in-house CMS.

Status: I no longer maintain this, but the site is still live with the same design and codebase.

Latti & Anderson PPC Landing Pages

Date: January 2010

Involvement: Development from a design mockup

Description: Part of my work for Nowspeed Marketing. Starting from a design comp by Rob McCrave II, I created three separate pay-per-click (PPC) landing pages in Drupal for Boston-based law firm Latti & Anderson, on the topics of general maritime law, the Longshore Act, and recreational boating. These pages were not linked from the rest of the site, but appeared in sponsored search results.

Status: The general maritime law and Longshore Act pages are defunct. The recreational boating one is still live, but now uses WordPress, and I no longer maintain it.

Technologies: HTML, CSS, Drupal 6

Lise’s HTML/CSS pet peeves, part 3 of 4: misuse of the !important flag

Remember these posts? I’ve been holding off on posting #3 because I realized I didn’t have as much as I thought to say about “nudging” with absolute and relative positioning. I would much rather talk about misuse of the !important flag. So, slight change of plan: I’m going to do that first.

Lise, what the hell is !important?

Not, in fact, a philosophical question.

If you’re a hobbyist CSS-slinger working mostly with your own code, you might not have ever heard of the !important flag. It’s the kind of thing that only really becomes relevant in large stylesheets, and usually only those touched by multiple developers.

I still recall, with something less than fondness, the first time I saw it. I was contracting as a front-end developer at a company that really wanted me to also be a designer and a back-end developer (for $30/hour — ha!) At first glance, I thought it was some sort of comment, like “this is important, do not delete.” I had to look it up.

What !important does, if you are unfamiliar, is move a CSS attribute to the head of the cascade.

So what’s the problem with it, Lise?

!important is kind of like a pushy jerk cutting in line, breaking the order which is the core of, you know, cascading style sheets. This is kind of a nuke-like power, and so it is important to use it sparingly.

So you say. Can you give me an example?

Let’s say you’ve just realized, after writing a bunch of CSS already, that you want ALL the <p> tags on your page to have a font-size of 15px, rather than setting it individually. You might write a style like this:

p {

As it happens, you also have a div called .box that has <p> tags inside of it, and you look to see that *gasp* these paragraphs are not obeying your command. They have a font-size of 14px, even though you said, right there on line 101, that all <p> tags should have a font size of 15px! This must not stand! You “fix” this by applying the important flag:

p {
	font-size:15px !important;

Whew. Problem solved, right? Your paragraph has a font-size of 15px, everyone is happy.

But… what you may not have realized is that, somewhere lurking in your stylesheet, there’s a style that says:

.box p {

… which you have just knocked over and taken the lunch of. Someone else — or an earlier version of you — has decided that paragraph tags within .box get the font-size of 14px, and you have just shot that style right in the head.

And? So what, Lise?

What happens if someone wants to override this style for another set of .box p elements? They will need an !important tag to override THAT style.

In a long enough stylesheet, you end up with an escalating war of the !important tags.

If this doesn’t seem that bad to you, imagine working on thousands of lines of CSS, much of it written by other people — which is what I do every day. The temptation in that instance, when your precious style is being overridden by something unwanted higher in the cascade, is to pull the pin on the !important grenade. It’s this use case:

  2. (use !important rule)
  3. OK, now it’s working

“When Using !important Is the Right Choice,” Chris Coyier,

And yet, this is exactly the sort of place where you should not do this.

All right, I’m beginning to see. So what should you do instead of applying an !important flag and breaking the cascade we all know and love?

Some options:

You can change or get rid of the style for .box p. Not always possible, but if you are the only front-end developer working on a project, you can refactor all you like. (Oh, for that kind of freedom!)
– If what you are trying to accomplish is: “All paragraphs have a font size of 16px, except for the ones inside of .box… oh, except for this one example,” the best thing to do is to work with the cascade by making a more specific style. Maybe you want a special sort of .box, a callout box, to have a larger font size. So you set:

<div class="box callout">

And then set a style of:

.box.callout p {

(This is also an example of modular CSS, which I like).

Cascading makes my head hurt.

Here’s a rule of thumb: the longer the style declaration, the more specific it is. Everytime you add a selector, you make it more specific.

Is there anything !important is good for?

!important is very useful for overriding styles you don’t want that come in from sources you can’t control, like inline styles on social media sharing buttons. Have no compunction about overriding Facebook’s shitty JS-applied inline styles for its Like button. It won’t hurt Zuck’s feelings any.

Go back to: Part 1 | Part 2

Lise’s HTML/CSS pet peeves, part 2 of 4: clearer divs

This post is about another of my front-end web dev pet peeves: clearer divs, and associated float/clear madness.

(For those of you not webbily-inclined, we are not talking about what happens when you flush the toilet. It is — slightly — more pleasant than raw sewage).

Clearer divs fit under the category of “extraneous markup”, but I’ve given them their own bullet point because they INFURIATE me. Seriously, seeing a document riddled with this:

<div class="clearfix"></div>

Or worse yet:

<div style="clear:both;"></div>

…is enough to send me into a raaaaaage.

To explain the annoyance factor here, I need to explain a little about floats and clears for the front-end web dev n00bs in the audience. Most website layouts these days are based around multiple <div>s made into columns by applying the style “float:left” or “float:right” to them. Take this bit of markup:

#box {
#left_column {
#right_column {
<div id="box">
   <div id="left_column">This is the left column</div>
   <div id="right_column">This is the right column</div>

The content within those <div>s will form themselves into two rudimentary columns which continue down the page indefinitely. Like this:

This is the left column and it goes on for as long as you have content to fill it
This is the right column and because it’s wider it can go on longer and longer and longer and longer and longer

Unfortunately, it’s that indefinitely wherein the problem lies. Elements that come after those two columns will continue to contort themselves to accommodate that float, unless you tell them otherwise. This can cause a number of strange behaviors that are boggling to CSS newbies — the source of 90% of problems when my friends come to me with their webpages and say, “You know CSS; make this work!”

“But Lise!” you say, “your two columns above aren’t have any problems.” Well, that’s because I have cleared them. If you know your way around Firebug/Chrome Dev Tools, try toggling off the style on #box. You’ll see something like this (picture):

Screen Shot 2014-10-02 at 6.58.57 PM

So floats are tricksy, like hobbitses. But they can be countered by the clear CSS property. I like to think of an element with “clear:both” on it as CSS Gandalf, spanning the width of the parent element and saying “None shall pass!”

… I’ve just compared balrogs and hobbits. This LOTR analogy is breaking down, so let’s leave it aside. Will miss pointy hat.

The easy, ugly way to clear a float is to put a new, empty element after it — within the parent element — with “clear:both” applied to it:

#box {
#left_column {
#right_column {
.clear {
<div id="box">
   <div id="left_column">This is the left column</div>
   <div id="right_column">This is the right column</div>
   <div class="clear"></div>

This will do the trick — your successive content won’t try to jump up into #box.

So what’s wrong with it?

Well, it’s non-semantic and extraneous markup, which we’ve already talked about a little. That <div> isn’t pulling its weight; it has no meaning on the page, and exists only for appearance reasons — rather like a Wodehouse protagonist.

Moreover, there are a bajillion (okay, five or so) other ways to clear floats (more) semantically. To name them:

Floating the parent (in this example, #box). Floated parent elements will expand to contain floated children. Understandably, this doesn’t work everywhere; you may not want that element to jog to the left.

Setting overflow:hidden or overflow:auto on the parent. This is the method I used above to wrangle our columns. Like with floated parents, elements with overflow:hidden on them will expand to contain floated children. It has a few cons to its use, however:

  • It’s not supported in IE7 or below. But none of us are supporting that any more, right
  • overflow:hidden interacts weirdly with box-shadows
  • Obviously, if you need a different value for the overflow property, this won’t work for you

That said, I find a lot of use for this one, and it tends to be my go-to clear method.

Set clear:both on an existing (unfloated) semantic element that follows. Here you’re doing what you’re trying to do with a clearer div, on an element that would be on the page anyway. Dependent though it is on a very specific structure, this method is worth mentioning because this is common way of building a two column layout — float one div left, float one right, and have a footer that spans the document beneath it. Put clear:both on the footer and you’re good to go.

The so-called easy clearing method (warning, dated), where you apply clear:both to an empty space inserted into the DOM via the :after pseudo-classes. I didn’t use this one for a long time, due to lack of support in IE7 or lower for these pseudo-classes. It’s also a tetch non-semantic. But with IE7 being phased out more globally, it has become the most generally applicable method of clearing something — all the previous methods only work in a subset of cases.

A slight improvement on this is the micro clearfix. If you use Sass with Bourbon, it’s the method you get if you use @include clearfix().

(And this is why I’m a front-end web developer — so I can say my job involves sass and bourbon).

One troubleshooting hint: if you’re seeing odd behavior on a page, and floats are involved, try inspecting the parent element in Firebug or Chrome Dev Tools. (You are using these, right?) If it appears with no height, and on selection doesn’t appear to wrap its child elements, there’s likely an uncleared float somewhere in there.

That’s enough info, right?


All right, all right. I will acknowledge there may be corner cases where you have to stick clear:both on a piece of markup that wouldn’t otherwise exist. But I have only rarely come across such cases.

In case this rant didn’t help you to understand floats and clears, I point you towards a couple of my favorite resources. They are both a few years old, but — aside from the browser bugs — floats and clears haven’t changed much in ten years.

Next time, HTML/CSS bugaboo #3 – “nudging” with absolute and relative positioning.

Lise’s HTML/CSS pet peeves, part 1 of 4

I’ve been a front-end web developer full-time since 2010, but I’ve been playing with HTML and CSS since 1997. I remember the paradigm shift from tabular layouts to CSS positioning. I remember IE for Mac. I recall the dark days before Firebug and Chrome Developer Tools. I remember *shudder* the <blink> tag.

And in that time, I’ve seen a lot of bad code*, mang.

In particular, there are four things I see again and again that bug me. They are newbie goofs, or they are the kind of things non-specialist** developers do. They are common mistakes which I guarantee I made a metric shitload of when I was first starting out.

I only hope that by sharing this, I can save you some time 🙂

The four pet peeves I’m going to address in four posts are:

  1. Extraneous markup
  2. Clearer divs (and general float/clear madness)
  3. Over-using absolute/relative positioning for “nudging.”
  4. Over-using the !important flag.

Let’s get right to the first one: Extraneous markup

This is rather broad, but let me give you an example, based on something I see a lot in my job:

<div id="box">
   <a href="#">
      <p>line 1 of text</p>
      <p>line 2 of text</p>

The purpose of this markup is to make a link that spans multiple block-level elements. This is not default behavior for a link–<a> tags are inline elements by default in most browsers–but it is possible and a common need. <div>s on the other hand are block-level by default. In essence you’re making the link block level by wrapping it in a block-level element.

It works, but you have to make sure the link expands to fill the <div> so the whole block is clickable, being sure to account for padding, etc…

… or you could just make the <a> block level. Seriously. It’s one line of CSS: display:block;. Just do it, and can the <div>. It gives you this slightly neater HTML:

<a id="box" href="#">
   <p>line 1 of text</p>
   <p>line 2 of text</p>

(I just did a test in Chrome, and it looks like these days you don’t even have to set display:block; on the <a>. I’m pretty sure this was not always the case).

Other things that get my goat:
“Spacer” blocks, i.e. empty elements that exist only to add space to a site design. Remember those days before CSS borders, when creating a vertical rule was hard? This is no longer the case! These days we have margin and padding and borders and outlines, and we should use them.
Elements with no styles applied to them. If a tree falls in the forest and no one is there to hear it, does it make a sound? If an element has no styles attached to it, can it really be said to live at all?
non-semantic markup in general, i.e. things like <p class=”red”>.

That’s all for now, but the next post deals with my favorite (not really) non-semantic markup bugaboo: clearer divs.

* I used to be pedantic about not calling HTML/CSS “code” because it’s not procedural. But a) I am softening in my old age, b) I also write JS these days, too, so I can get away with it.
** Unsolicited opinion time: I think “full-stack development” is getting to be a worse and worse idea every day. The body of knowledge in front-end development has become large, and I think it’s unrealistic to expect someone who’s spent their career hacking at C++ to have a thorough understanding of floats and clears, the cascade, and cross-browser quirks.