Skip to main content
Close-up of a laptop, with the screen showing code.

From Comp to Code: The Journey of a Button

Angela Hanshaw

By Angela Hanshaw ,

Senior Interactive Developer

April 22, 2016

Technology

There’s a lot that goes on between when clients sign off on a design and when the concept comes to life as a page or site. That’s when the front-end developers go to work, and the journey from the design comprehensive, or comp, to code begins. Here’s a glimpse into what goes into the coding process.

In this case, the journey started with a simple question from our lead developer: Would you like to make a button?”

Button example orig

Sure, that’ll be easy, I thought.

There are just two minor things,” he added. The size of the button will need to change based on its content, so you can’t use a height or width in the CSS, and you can only use <button>text</button> — no additional classes or spans can be added to the html.”

Hmm. That makes things a little more interesting. Why, you ask? Well, to accommodate a button with two backgrounds (in this case, solid blue and striped blue), I would typically add a <span> within the <button> html, like this

<button><span>Click Me!</span></button>

And use the following CSS:

/* create striped background */
button {
 padding:0 0.438em 1.063em 0; /* push the striped background down and to the right */
 background:url('button-stripe.png') repeat;
 border:0; /* remove default border */
 border-radius: 0; /* remove default border radius */
}

/* style text & create solid background */
button span {
 position:relative /* fix for IOS positioning */
 font-size:1.063em; letter-spacing:.05em;
 color:#fff;
 padding:0.625em 1.875em; /* padding determines size of button */
 background-color:#5898cf;
}

The result:

But since adding <span> wasn’t an option, my first thought was to try using multiple backgrounds on the button:

button {
 font-size:1.063em; letter-spacing:.05em;
 color:#fff;
 padding:0.625em 1.875em;
 background-image: url('button-bkgd.png'), url('button-stripe.png');
 background-size: 100% 100%, 100% 100%;
 background-repeat: repeat, repeat;
 background-position: left top, 1.250em 1.250em;
 border:0; border-radius:0;
}

The result:

After a few different attempts at positioning the backgrounds, however, it quickly became clear there wasn’t a way to make them overlap correctly without using height/width.

Okay, so now I knew I could only use one background image, and would need to figure out a different way to create the solid blue part of the button. Maybe box-shadow would work? After some trial and error, I discovered that I could use an inset box shadow with large vertical/horizontal offsets. I then added transparent borders on the bottom and right to reveal the striped background.

button {
 font-size:1.063em;
 letter-spacing:.05em;
 color:#fff;
 padding:0.625em 1.875em;
 background:url('button-stripe.png') repeat; /* create striped background */
 box-shadow: inset 3.750em 3.750em 0 #5898cf; /* create blue background */
 border:0;
 border-right: 0.438em solid transparent; /* hide part of blue background */
 border-bottom: 0.438em solid transparent; /* hide part of blue background */
 border-radius:0;
}

Almost there, but I still wasn’t getting the overlapping effect I needed. The solution? Add a second box shadow with a negative offset to extend the top and left sides of the blue background, then adjust the padding to re-center the text.

button {
 font-size:1.063em;
 letter-spacing:.05em;
 color:#fff;
 padding:3px 30px 10px 23px; /* accommodate new box shadow */
 background:url('button-stripe.png') repeat;
 box-shadow: inset 3.750em 3.750em 0 #5898cf,
 -0.438em -0.438em 0 #5898cf; /* extend blue background */
 border:0;
 border-right: 7px solid transparent;
 border-bottom: 7px solid transparent;
 border-radius:0;
}

The result:

And all was perfect — until I started browser testing. In some versions of Internet Explorer there were very thin white lines on the top and left edges of the main box shadow. Fortunately, this was a simple fix. Using pseudo elements, I added thin blue lines to cover the edges:

button {
 position:relative; /* accommodate absolute positioning of new pseudo elements */
 font-size:1.063em;
 letter-spacing:.05em;
 color:#fff;
 padding:0.188em 1.875em 0.625em 1.438em;
 background:url('button-stripe.png') repeat;
 box-shadow: inset 3.750em 3.750em 0 #5898cf, -0.438em -0.438em 0 #5898cf;
 border:0;
 border-right: 0.438em solid transparent;
 border-bottom: 0.438em solid transparent;
 border-radius:0;
}

/* hide top line */
 button::after {
 content:''; position:absolute;
 top:-1px; left:0;
 width:100%; height:2px;
 background-color:#5898cf;
}

/* hide left line */
 button::before {
 content:''; position:absolute;
 top:0; left:-1px;
 height:100%; width:2px;
 background-color:#5898cf;
}

The result:

Finally, I added a hover state, and the button was ready to go:

button:hover {
 background-image:url('button-stripe.png');
 box-shadow: inset 3.750em 3.750em 0 #497dab, -0.438em -0.438em 0 #497dab;
} 

button:hover::after,
 button:hover::before {
 background-color:#497dab;
}

The final result:

And here’s the Sass-ified version:

button {
 position:relative;
 font-size:1.063em;
 letter-spacing:.05em;
 color:#fff;
 padding:0.188em 1.875em 0.625em 1.438em;
 background:url('button-stripe.png') repeat;
 box-shadow: inset 3.750em 3.750em 0 #5898cf, -0.438em -0.438em 0 #5898cf;
 border:0;
 border-right: 0.438em solid transparent;
 border-bottom: 0.438em solid transparent;
 border-radius:0;
 transition: background-color .3s ease;

 &::after {
 content:'';
 position:absolute;
 top:-1px;
 left:0;
 width:100%;
 height:2px;
 background-color:#5898cf;
 }

 &::before {
 content:'';
 position:absolute;
 top:0;
 left:-1px;
 height:100%;
 width:2px;
 background-color:#5898cf;
 }

 &:hover {
 background-color:#fff;
 background-image:url('button-stripe-hover.png');
 box-shadow: inset 3.750em 3.750em 0 #497dab, -0.438em -0.438em 0 #497dab;

 &::after,
 &::before {
 background-color:#497dab;
 }
 }
}

Because of the project constraints, this simple button turned out to be one of the more challenging (and fun!) things that I’ve worked on here at Elevate. It provided a unique opportunity to take CSS elements I was already familiar with and use them in new and unexpected ways. It’s also a great example of how much work goes into even seemingly simple elements. As a front-end developer, I need to make sure that everything on a page matches the designer’s vision, works across multiple browsers, loads quickly, and accommodates any special requirements or restrictions that a project may have.

Related Posts

Crichton 0718 meta orig

Content Management Solutions for Ecommerce

Decoupling the management of your marketing content from your ecommerce system can open up a new world of opportunity for your team.

Crichton 0817 meta orig

Benefits of Performance Budgets and Real User Monitoring: Site Performance, Part 2 of 3

In part 2 of this series, our we share tools and techniques that improve performance as well as important factors to keep in mind to help ensure success.