Problem
Sass code for creating a basic search box. Resulting CSS used for two that are different widths.
The goals is to define sass that generates CSS that is easily re-usable as well as concise and efficient and to keep the initial definitions as DRY as possible.
Review:
- Coding style
- Re-usability
- DRY principles
SASS:
$container-width:940px;
$search-container-padding:54px;
$form-width:$container-width - ($search-container-padding * 2);
$form-height:47px;
$button-width:118px;
$search-container-background:#e9e9e9;
$form-background:#fff;
$input-border:1px solid #dadadc;
$focus-border:1px solid #052546;
$input-br:4px;
$input-inset:15px;
/*
input width, sets the width of an imput and adds polyfill placeholder correctly
*/
@mixin input-width($width)
{
.search-input
{
width:$width;
}
.search-placeholder
{
left:$form-width - $width - $button-width + $input-inset;
}
}
.search-container
{
box-sizing:border-box;
width:$container-width;
background-color:$search-container-background;
padding:30px $search-container-padding 0;
}
.case-search-container
{
padding-bottom:20px;
}
.book-search-container
{
height:124px;
}
.search-form
{
box-sizing:padding-box;
width:$form-width;
height:$form-height;
position:relative;
background-color:$form-background;
border:5px solid $form-background;
border-radius:6px;
input[type=submit],
button[type=submit]
{
width:$button-width;
height:$form-height;
position:absolute;
top:0;
right:0;
background:image-url("structure/button-sprite.png") 0px 0px no-repeat;
cursor:pointer;
border:0px;
color:#fff;
font-weight:bold;
text-transform:uppercase;
&:hover{
background-position:0px 0 - $form-height;
}
}
.text
{
input
{
box-sizing:border-box;
height:$form-height;
position:absolute;
top:0;
right:$button-width;
border-top:$input-border;
border-bottom:$input-border;
border-left:$input-border;
border-radius:$input-br 0 0 $input-br;
margin:0;
padding:10px $input-inset;
&:focus
{
outline:none;
border:$focus-border;
}
}
}
.search-placeholder
{
position:absolute;
top:13px;
z-index:10;
font-size:15px;
}
}
/* specific width over-rides and label placement relative to this */
.book-search-form
{
@include input-width(714px);
}
.case-search-form
{
@include input-width(455px);
}
HTML:
<section class='search-container case-search-container'>
<form class='search-form'>
<label class='placeholder-label'> <!-- IE8 friendly placeholder polyfill -->
<div class='text'> <!-- cake generated inputs -->
<input class='search-input' type='text' ... />
</div>
<div class='submit'>
<input type='submit' ... />
</div>
</form>
</section>
<section class='search-container book-search-container'>
<form class='search-form'>
<label class='placeholder-label'> <!-- IE8 friendly placeholder polyfill -->
<div class='text'> <!-- cake generated inputs -->
<input class='search-input' type='text' ... />
</div>
<div class='submit'>
<input class='submit' ... />
</div>
</form>
</section>
Solution
Sass
If this is meant to be a reusable Sass library, you’ll want to make use of default variables so that they’re easier to override:
$container-width: 940px !default;
$search-container-padding: 54px !default;
You’ll want to do something similar with your mixins so that the values can be changed for one-off instances:
@mixin input-width($width, $form-width: $default-form-width, $button-width: $default-button-width, $input-inset: $default-input-inset)
{
.search-input
{
width:$width;
}
.search-placeholder
{
left:$form-width - $width - $button-width + $input-inset;
}
}
You’ll probably want to avoid generating styles by default, since the user might not want them. It is a common request for people who use libraries like Bootstrap and Foundation: how do I make it stop generating default styles? Instead, you might want to consider having a separate file that can be imported that generates these styles.
The $input-br
variable has an ambiguous name. When I initially saw it in the source, I thought it was for the br
element. It wasn’t until later I realized br
was being used as an abbreviation for border-radius
(none of your other variables are abbreviated).
Sass has a bit of a shortcut you can use for some properties:
border: {
top: $input-border;
bottom:$input-border;
left:$input-border;
radius: $input-br 0 0 $input-br;
}
CSS
If the background image for your button fails to load, the button is completely invisible because it is white text on a white background.
The use of px units here is sub-optimal. When your containers contain text, you should be using a unit that’s relative to the font-size, like em or ex, to specify its measurements. If the user changes their browser’s font settings in such a way that they want their font size to be 20px at the bare minimum, then your content is going to spill out of these containers.
Using archaic widths of yesteryear (900px~1024px) are very unfriendly towards mobile devices. Set a max-width if you must, but avoid setting hard widths that are likely to cause horizontal scrolling. Better yet, look into responsive design.
HTML
Placeholder text is not meant to be a replacement for labels, please don’t treat it as such. It should be thought of as example content only.
Labels must have a closing tag. If they’re not containing the input element that they’re for, they need to have a for
attribute and the associated input element needs to have an id
with the matching value.
There’s a new input type of search
that I recommend using instead of text
for your search input fields. Browsers that don’t support search
will fallback and use text
anyway.
Your 2nd submit button has a class of submit
rather than a type.