codeforamerica / ohana-web-search

A mobile-friendly website for finding human and social services in your community
http://ohana-web-search-demo.herokuapp.com
BSD 3-Clause "New" or "Revised" License
69 stars 74 forks source link

CSS themes #464

Closed declan closed 10 years ago

declan commented 10 years ago

I'd like to be easily able to "re-skin" Ohana Web Search, to allow us to stand up a new instance for a customer with their logo and branding.

Note sure if this requires changes to the structure of the CSS, or just better documentation about which variables/classes/whatever to customize? Either way I'm happy to start the work in our fork and submit a pull request, but I'd appreciate your guidance on where to start looking.

anselmbradford commented 10 years ago

@declan Here's the current theming landscape:

Logo Currently, the logo filename is set in /config/settings.yml, however, the dimensions likely will need to be a customization potentially set in /config/settings.yml as well, since very different dimensions will shift the layout potentially. I have https://github.com/codeforamerica/ohana-web-search/issues/452 open, which has an overarching issue to address positioning of the logo in a smarter way to handle changes in width. The logo should center-align on mobile and left align with padding on desktop. The probable scenario is to set the logo dimensions in /config/settings.yml and then have a function in the SCSS (in this file) that can be used to include the logo dimensions in layout calculations where it matters.

CSS Structure The project uses SCSS with Compass, which allows the defining of things like functions and variables for CSS, as well as allows the CSS to broken into logical chunks. There's a number of practices for structuring a compass/SCSS project, which I've attempted to pull the most logical parts out of based on our project needs. (Our structure most closely follows the structure defined in this Lynda.com tutorial if you have access there and are curious.)

The structure is like this:

So I think what to aim for is making _variables.scss more robust and documented. What do you see as important to be able customize?

declan commented 10 years ago

Thanks @anselmbradford, this great. We'll start playing with _variables.scss and see where that gets us. First impression is that that would take care of most of what we're looking for.

anselmbradford commented 10 years ago

Cool, keep me updated on where you find issues. Some other things to note:

(FYI – I updated my earlier comment as I noticed a typo.)

declan commented 10 years ago

We've been working on customizing the color scheme, overall with pretty good success. Here is a summary of our experience.

What worked well

We started by renaming the color variables to $primary, $secondaryA, etc., because we were getting confused working with semantic variable names like $blue once it was no longer actually blue. (See _variables.scss.)

Having the colors defined in _variables.scss made it really, really easy to play around with different color schemes. This was absolutely great, and exactly what I was looking for when I opened this issue. In fact, we made a half-dozen different color schemes, which you can see live through these links:

Main challenges

The main difficulty we ran into is that shading also plays a large role in the design, and shading is not easy to customize. For example, the left sidebar has a lightest($primary) background and darkest($primary) text. This means first of all that the primary color can't be too light or two dark, or the text becomes unreadable. It also means that there is no clean way to make that text a different color from its background.

Practically speaking, this limits the range of color schemes that can be easily made to look good by modifying _variables.scss. We started out with this color scheme but to implement it we had to make about 35 changes scattered across the 5 CSS files. Most of them had to do with changing the shading. The others involved switching occurrences of $black to $white and vice versa. Overall we felt like the heavy use of shading took some flexibility out of our efforts to change the styling.

Speaking of shading, another thing we noticed was that $complementaryA is never used directly. Instead there are about 19 occurrences of darkest($complementaryA) and 10 occurrences of lightest($complementaryA). Again, we feel like this took some flexibility out of our choice of colors, because instead of being able to choose a light complement and a dark complement, we had to choose a midrange one that would look ok whether it was lightened or darkened.

Next Steps

I can imagine a couple of different next steps. If the use of shading is something deliberate that you want to stick with, we can write up our findings about what kinds of color schemes work well with the current setup, and if you like you can publish that either as part of the wiki or as a markdown page. (In particular, we found that monochromatic color schemes tend to look good, see the links above).

Otherwise, would you be open to having us do some refactoring where we pull some of the differences in shading out into variables? I think this would give more flexibility to anyone trying to re-theme the app, and also make it clearer what is going on. It wouldn't require any modifications to your current color scheme, since I could simply set one variable to be a darkened version of the other, for example something like $darkComplement: darkest($complementaryA).

declan commented 10 years ago

@anselmbradford

After thinking about it a little more, the refactoring of the color variables seems like a smallish change, so I'm going to go ahead and start working on it in a separate branch. Just let me know if there's anything I should keep in mind.

anselmbradford commented 10 years ago

Thanks for the great write-up! A couple thoughts:

Shading

What is the difference to having a variable $darkComplement that's used outside of _variables.scss and using the shade function darkest($complementaryA) directly? This would be so you could change the color that was darkened? Like have the ability to change it to darkest($complementaryB)? We actually did have the shading/tinting pulled out into its own variables in the past (see here). My thought on the current structure was to reduce the number of colors in _variables.scss that needed to be updated—although, as you discovered this does come at the cost of some flexibility. In the prior iteration, the shading/tinting of colors were set using rgb() notation and I had a reference color scheme table in Adobe Illustrator (I actually have a script to automatically generate these values here). However, since these values used rgb() notation, it was manually intensive to say, for instance, lighten all colors. This was before I had the color functions in _functions.scss. Based on your feedback, perhaps the approach to take would be to place the five base colors, plus black and white (these should probably be $monochromeA and $monochromeB based on current naming) at the top of the variables color scheme section, and then re-introduce the shading/tinting variables below, but have their values use the color function in _functions.scss by default.

Sidenote... note with the naming of the variables that they should follow the rule of specificity and go from general → specific, so instead of $darkComplement it would be $complementDark (or $complement_dark), if complement is the general color being described, and dark is the specific shade.

Opacity

Some places use opacity, so for pulling out the shading/tinting into the variables, the shade/tint functions used in _functions.scss should probably be used directly in _variables.scss and then have an opacity() function in _functions.scss that take a color and alpha value. The opacity would then be set outside of _variables.scss, like opacity($complement_dark, 0.5).

Helper functions

Compass provides a number of color helper functions. Currently, tint and shade are used from these, but with set 25% white/black saturation increments to reduce the number of variables. There's also a helper function for creating color contrasts, which might be helpful to investigate.

Next Steps

I think pulling out the shading variables makes sense, since it seems necessary for your customizations. Do you see an alternative to this? Reducing the colors down to the five bases I don't think would be enough colors to work without having shading/tinting. If you see areas where these are not needed (like I wonder about the text-shadow on the homepage search button text), it would be good to make note of those. Like that $complementaryA is never used directly is a good point.

Also, I'm forgetting if there are instances of this... but if a shade color+opacity is used on top of a base color, these occurrences could possibly be refactored to use black with an opacity, so that the base color and the shade color do not have to use the same color, but the shade would mix in black directly to whatever the base color was.

anselmbradford commented 10 years ago

Also, you might be curious to check out this branch --> https://github.com/codeforamerica/ohana-web-search/tree/style-guide/ ... this will give you a /styleguide/ directory (in /public) where you can see the UI component and color scheme visualized as color swatches. I'd be interested in developing this further as an aid in theming.

declan commented 10 years ago

First, a quick response to your points above:

Extracting shades into color variables

We've got an experimental branch where we replaced every occurrence of darkest($primary) with $primary_darkest, every occurrence of dark($primary) with $primary_dark, and so forth. We also counted the number of occurrences of each color. (Take a look at the code and frequences here.) This is intended as an exploratory step, not a final solution.

We also made a few versions of the site where everything is grey except for one color, which made it really easy to see what is being used where.

Some colors not used very much

Doing this made it pretty obvious that 3 of the base colors are not being used very much.

I know you're concerned that the 5 base colors won't be enough without shading/tinting, and I do agree with that. At the same time, given that the secondaries and complementB are not used very much, I feel like we could do cleanup on which colors are being used where. What exactly that means I'm not sure yet, but we'll get you some ideas by Monday.

declan commented 10 years ago

We took a look at how Bootstrap organizes their color variables. They start by defining their color palette with names like $brand-primary and $brand-info, and then go on to define another set of variables for things like $btn-primary-background, where they reference the color palette variables. I really like this approach because

With that in mind, we've been extracting colors into variables with semantic names like $btn-color. The code is pretty messy right now but we'll have a clean version for you guys to look at later in the week.

We're being really careful not to alter the visual appearance of your site, these changes are all under the surface. With that said, though, we just tried retheming the site again, and found that we already have a lot more control over the colors, so we think this is a good step forward in making the site customizable. Hopefully you'll agree!

anselmbradford commented 10 years ago

@declan Thanks again for all your work and consideration of the approach here!!

The semantic naming makes sense. I've seen this before with, for instance, breaking link styles into variables based on semantic sectioning of the page (e.g. $link_header, $link_body, $link_footer). I'd gone down this route a bit but worried about it becoming too convoluted, and I do think we need a methodology around when and how semantic color variables are created and used. Some thoughts on this are:

Any thoughts on these points?

declan commented 10 years ago

@anselmbradford thanks for the quick and thoughtful feedback!

Does that all sound ok to you?

declan commented 10 years ago

ARIA describes different types of roles for elements. Some elements have "widget roles", like button, some have "document structure roles", like list, and some have "landmark roles", like search.

For an element like the lists of common search terms on the home page, would you prefer the variables to have names like search-list-color, or list-search-color? I.e. if a widget or structural element needs to look different within a specific section of the page, do you think the convention should be to start with the widget role or the landmark role?

declan commented 10 years ago

We've pulled out 57 named variables (for reference, Bootstrap has 368). At this point we are able to completely re-theme the site to our satisfaction just by adjusting the values of those variables. For most color schemes that we've tried, we're able to do it without altering more than 10.

I'd like to get your input on what work still needs to get done before it makes sense to open a pull request. In particular,

declan commented 10 years ago

Oh, right, and a link to the code... https://github.com/purplebinder/ohana-web-search/tree/464-refactor-color-variables

anselmbradford commented 10 years ago

Cool, I'm take a look as soon as possible!

anselmbradford commented 10 years ago

@declan Okay, got a chance to look through these. Thanks for your patience!

For an element like the lists of common search terms on the home page, would you prefer the variables to have names like search-list-color, or list-search-color? I.e. if a widget or structural element needs to look different within a specific section of the page, do you think the convention should be to start with the widget role or the landmark role?

Hmm, this could really go either way, but I think if we're going with a component-centric model, it would make the most sense to put the widget first, unless the variable is for theming a landmark directly. So then, for instance, for links, link is the general thing that appears site-wide and banner is a specific area on the page, so link-banner would be general → specific, as it's saying of the general category of links we're talking about the specific ones in the banner. (If we came at it from a site-wide approach it would be the reverse. banner would be the general area in the page, and link would be the specific widget in that area.)

How does this structure look:

[widget]-[landmark | structure]-[non-WAI-ARIA qualifier]-[state]-rule

... where:

[widget] = the specific widget. This would usually be present, but could be [optional] in cases there the variable was applying a style (such as a background color) to the containing landmark area. [landmark | structure] = the [optional] landmark or document structure the widget appears in. [non-WAI-ARIA qualifier] = an [optional] descriptive qualifier for differentiating this variable, which is not covered succinctly in WAI-ARIA. See note below* [state] = the [optional] CSS pseudo-class being set (e.g. hover, active, etc.) rule = the CSS rule being set (e.g. background-color, color, etc.)

* The non-WAI-ARIA qualifier would be for differentiating overlapping roles that weren't otherwise differentiated by WAI-ARIA. So Twitter Bootstrap names could be used here, for instance. For example, pagination would technically fall under the navigation WAI-ARIA landmark, however, there could be other navigation landmarks on the page, causing a name collision. These could either be differentiated by hyphenating the landmarks (navigation-main, navigation-banner, etc.) or providing a descriptive qualifier (navigation, navigation-pagination, etc.). Leaving off the optional [landmark | structure] would leave these with just pagination as you have it now.

Some of the names could be quite long, but I think this is okay, since someone theming this would be expected to just change the values, not use the variables directly. Also, the additional optional qualifies in the name would be the exception, not the rule. But there theoretically could be instances like $menuitemcheckbox-complementary-location-filter-hover-background-color. Do you see any issue with this?

Do the variable names make sense? At this point I have been staring at them for so long I have absolutely no idea.

Overall looks good. A few comments:

button_banner_hover_background-color

I don't have a strong preference either way. What do you'll prefer?

Do we need more comments in _variables.css? Just for clarifying when a role is not being taken from WAI-ARIA I think, otherwise I think what you have is fine.

There are still many places where color names like $primary are used directly in the style rules. As I said, this wasn't a barrier to re-theming with any of the color schemes we tried, but if you want I could go through and finish extracting all the colors into semantic variables. I have mixed feelings about whether that would be valuable or not.

We can be iterative about this. As you mentioned earlier, there's button variables that need further cleanup so they aren't in _base, so I think if you're not finding a barrier to theming what you have cleaned up is okay at this point.

Another note of guidance: You may have noticed the WAI-ARIA concepts include a "Related Concepts" row in its entries. So, for instance, the navigation role has a related concept of nav element. This means it should correspond and be applied to an HTML <nav> element on the page. This interconnected meaning can help define the structure for the HTML, WAI-ARIA, and the CSS. So ideally there's:

A semantic HTML element that is a related concept to a WAI-ARIA role that has a style variable that references the WAI-ARIA role.

declan commented 10 years ago

Great, thanks for looking at the code and for your feedback. I'm going to standardize the variable names in line with your suggestions and then submit a pull request.

Let's stick with dashes in the variable names to be consistent with Compass.