Photoshop to CSS Conversion: 3 Methods Compared
Converting Photoshop mockups to live web code is an extremely common practice among web designers. We’ve all done it a million times by hand, so it’s pretty exciting when we start seeing solutions pop up that will help us automate this process.
The latest version of Creative Cloud Photoshop CS6 has a built-in feature for converting Photoshop styles to CSS, and if you need another solution, there are two solid extensions that you can check out. Today we’ll compare the results of all three methods: Photoshop, CSS3Ps and CSSHat to see which is best.
Our Three Candidates
This article is all about comparing the results from three different methods of achieving the same goal. We have a design in Photoshop and we want to see it built in HTML and CSS.
Our three methods include Photoshop itself (version 13.1) as well as two extensions CSS3Ps and CSSHat. I recently created a screencast for Psdtuts+ that introduces and does some comparison between Photoshop and CSS3Ps, which you can find here.
I didn’t cover layer group functionality in that tutorial though so I thought it was worth another go and decided to toss in CSSHat as well so we really cover the bases well.
Our Test Case
We’ll need something to test the different conversion methods on, so I whipped up a generic UI panel that could hold anything you want:
This is basically comprised of three different layers: the text layer, the top bar and the background. Here I separated them out a bit so you could get an idea of how they were constructed.
Below you can take a look at our layers palette. Note that this object is structured very intentionally. All three of the methods that we’ll look at today convert layer names to class names in CSS, so you want to be sure that you’re very careful about how you name your various pieces. Also note that the shapes are made from vector shape layers.
Some of the methods that we’ll try out support layer groups, which means we’ll want to convert the structure here to a div structure in our HTML.
HTML
Photoshop can take care of the CSS for us, but we’re still on our own with HTML. Here’s a quick attempt at an HTML structure that will work with the code that Photoshop is going to generate. Without this in your HTML, the CSS won’t do a thing!
<div class="panel"> <div class="paneltop"> <p class="type">Quick Panel</p> </div> <div class="panelback"></div> </div>
Photoshop
Let’s start off with the built in Photoshop functionality. The process here is extremely easy, all we have to do is select our layer group in the Layers panel and go to Layer>Copy CSS (you can also access this command with a right-click).
Photoshop provides pretty much zero feedback that anything has happened at this point. There are no options to tweak, no panels to inspect, just the menu command that we clicked above, which places a big chunk of code into our clipboard. Here’s the output, straight from Photoshop.
.panel {
position: absolute;
left: 180px;
top: 25px;
width: 360px;
height: 427px;
z-index: 7;
}
.type {
font-size: 19.913px;
font-family: "Helvetica";
color: rgb( 255, 255, 255 );
line-height: 1.11;
text-align: center;
-moz-transform: matrix( 1.70449868947994, 0, 0, 1.72443193254442, 0, 0);
-webkit-transform: matrix( 1.70449868947994, 0, 0, 1.72443193254442, 0, 0);
position: absolute;
left: 83px;
top: 25.902px;
width: 180px;
height: 27px;
z-index: 6;
}
.paneltop {
background-image: -moz-linear-gradient( -90deg, rgb( 1, 98, 171 ) 0%, rgb( 0, 52, 91 ) 100%);
background-image: -webkit-linear-gradient( -90deg, rgb( 1, 98, 171 ) 0%, rgb( 0, 52, 91 ) 100%);
position: absolute;
left: 2px;
top: 1px;
width: 351px;
height: 81px;
z-index: 4;
}
.panelback {
border-radius: 20px;
background-color: rgb( 224, 225, 226 );
box-shadow: 1.5px 2.598px 5px 0px rgb( 0, 0, 0 );
position: absolute;
left: 2px;
top: 1px;
width: 351px;
height: 418px;
z-index: 3;
}
The Result
If we toss this into a code editor and take a look at the result, the results are a little disheartening. Photoshop didn’t do a great job with the conversion. For starters, the top bar doesn’t have rounded corners. Also, the shadow seems to be at full opacity (too dark) and the type placement is off. If gives us a strong start and genuinely saves us a lot of time, but it’s probably not the magic solution you were hoping for from Photoshop.
See it live: Click here
To make things worse, if we jump back and look at the code, there’s plenty to complain about. There are some really wonky things going on here such as the unnecessary transform on the text. It seems that you can let Photoshop write CSS for you, but I’m not convinced that you should.
CSS3Ps
Our next candidate is CSS3Ps, a completely free Photoshop plugin that predated the built-in Photoshop functionality. The website shows some pretty complex examples so hopefully this will tackle our project a little better.
With the CSS3Ps extension installed, go to Window>Extensions>CSS3Ps. Then select the layer group and click the logo that pops up inside of the CSS3Ps panel.
Once you press that button, a web page opens up and presents you with a timer. You’re forced to wait twenty seconds and look at an ad, which sucks but given that the extension is free, it’s understandable.
From here you’re taken to a page containing the code, which I copied and pasted below. Note that this time around, I had to add in periods before the class names. CSS3Ps takes the layer name exactly as it appears in Photoshop, so you add in the “.” or “#” symbols there.
.type { font-family: Helvetica; font-size: 10px; color: #fff; } .paneltop { width: 351px; height: 81px; -webkit-border-radius: 20px 20px 0 0; -moz-border-radius: 20px 20px 0 0; border-radius: 20px 20px 0 0; background-color: #000; background-image: -webkit-linear-gradient(top, #0162ab, #00345b); background-image: -moz-linear-gradient(top, #0162ab, #00345b); background-image: -o-linear-gradient(top, #0162ab, #00345b); background-image: -ms-linear-gradient(top, #0162ab, #00345b); background-image: linear-gradient(to bottom, #0162ab, #00345b); } .panelback { width: 351px; height: 418px; -webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px; background-color: #e0e1e2; -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.34); -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.34); box-shadow: 2px 3px 5px rgba(0,0,0,.34); }
The Result
There’s a lot to like about the CSS3Ps output. For starters, it treats each individual layer as its own object and doesn’t attempt to position them over each other. I actually prefer this and always immediately strip out the absolute positioning code that the built-in method uses. This keeps the focus of the conversion where it should be: on style.
See it live: Click here
Speaking of style, the results in that area are improved as well. Notice how the top bar actually has a border-radius this time around and how the box-shadow uses an alpha value to reduce the opacity. This version might be a little prefix heavy on things that no longer require prefixes, but otherwise the code isn’t half bad.
Also, the fact that you can get the output reformatted in Sass or SCSS is a killer feature that easily makes this method better than the default Photoshop feature.
CSSHat
The third and final method that we’re going to check out is CSSHat. Like CSS3Ps, it’s a Photoshop extension, but this one will run you about $30.
To use CSSHat, simply select the layer that you want to convert and open the CSSHat panel (find it in the extensions menu as with CSS3Ps above). Unfortunately, CSSHat currently doesn’t support layer groups, so you’ll have to do it on each individual layer. This is a serious strike against CSSHat, but it makes up for it in versatility.
I love that I finally have some options to tweak. The other two methods were easy, but if you don’t like something, tough! Here I can toggle four different options: comment explanations, browser prefixes, layer dimensions and whether or not the code gets wrapped in a rule named after the layer.
Also notice that you can get the output in an impressive variety of formats: CSS, SCSS, Sass, LESS, Stylus and Stylus CSS. Here’s the output for the plain CSS version:
.type { color: #fff; /* text color */ font-family: "Helvetica"; font-size: 10px; } .paneltop { width: 351px; height: 81px; -moz-border-radius: 20px 20px 0 0; -webkit-border-radius: 20px 20px 0 0; border-radius: 20px 20px 0 0; /* border radius */ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; /* prevents bg color from leaking outside the border */ background-color: #000; /* layer fill content */ background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDM1MSA4MSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjUwJSIgeTE9Ii0xLjQyMTA4NTQ3MTUyMDJlLTE0JSIgeDI9IjUwJSIgeTI9IjEwMCUiPgo8c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjMDA2MWFiIiBzdG9wLW9wYWNpdHk9IjEiLz4KPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAzMzViIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgPC9saW5lYXJHcmFkaWVudD4KCjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIzNTEiIGhlaWdodD0iODEiIGZpbGw9InVybCgjaGF0MCkiIC8+Cjwvc3ZnPg==); /* gradient overlay */ background-image: -moz-linear-gradient(top, #0061ab 0%, #00335b 100%); /* gradient overlay */ background-image: -o-linear-gradient(top, #0061ab 0%, #00335b 100%); /* gradient overlay */ background-image: -webkit-linear-gradient(top, #0061ab 0%, #00335b 100%); /* gradient overlay */ background-image: linear-gradient(top, #0061ab 0%, #00335b 100%); /* gradient overlay */ } .panelback { width: 351px; height: 418px; -moz-border-radius: 20px; -webkit-border-radius: 20px; border-radius: 20px; /* border radius */ -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; /* prevents bg color from leaking outside the border */ background-color: #dfe0e2; /* layer fill content */ -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.34); /* drop shadow */ -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.34); /* drop shadow */ box-shadow: 2px 3px 5px rgba(0,0,0,.34); /* drop shadow */ }
The Result
As you can see above, the chunk of code this time is pretty huge, mostly due to the fact that the gradient is converted to a data URL. Below is the result if we paste directly into our code editor.
See it live: Click here
As you can see, just as with CSSPs, the elements are merely styled, not positioned, we would have to push them into place ourselves. On that front, the styles look perfect with the exception of the text, which is tiny. I expect this has to do with the fact that I built the Photoshop version on a Retina screen though so you may not experience this bug (CSS3Ps actually did the same thing).
Who Wins?
None of the methods for converting Photoshop styles to CSS outlined above are perfect. The Photoshop version works, but the code is pretty ugly and the results don’t utilize the advanced CSS3 techniques that you’ll need to match things like opacity and complex border-radius setups. CSS3Ps is free and performs better than Photoshop, but the method of turning you to a web page that is hidden behind a twenty second ad delay is pretty annoying.
CSSHat is the best in the bunch as far as customization, but it doesn’t support layer groups. The default Photoshop method is the only one that positions your multiple items in a way that matches your canvas, which could be a good or bad thing (I wish it were an optional feature). Ultimately, nothing is going to give you the accuracy, power and versatility of coding by hand, but these tools can get you off to a strong start and save you some serious time.
Personally, I tend to favor CSSHat in this bunch. It’s a little pricy, but the functionality is stellar. It’s frankly a lot closer to what I wanted to see from Adobe. I think they really dropped the ball on this feature and I recommend both CSSHat and CSS3Ps over what you get inside of Photoshop 13.1.
What Do You Think?
Now that you’ve seen my assessment of these three tools, it’s time for you to chime in. Which of the above methods have you tried? Which do you think is the best? Let us know in the comments below!