Skip to main content
Back to Blog

From Comp to Code: The Journey of a Button

Angela Hanshaw

By Angela Hanshaw

Interactive Developer

Category

Technology

April 22, 2016

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

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;
}

The result:

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;

    &::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

The Power of Early Design and Development Collaboration

Because web technologies evolve quickly, having a developer in your workflow process at the beginning can make a big difference in ensuring a project runs smoothly.

READ

Using Vagrant and Puppet in a Team Environment

In the past year, Elevate has been experimenting with automating the setup of our development and production server environments. We thought it would be beneficial to outline our journey using Vagrant and Puppet.

READ