We organize our SASS files very carefully. One file per component, careful naming, strict rules about overriding a component's internal classes (".mycontainer .somecomponent .somecomponent_title" is illegal). It's still painful.
One reason is cascading. The way CSS applies to trees means that every component has to be aware of what properties it could accidentally inherit. So to code defensively, you override things like colors and fonts. Using SASS mixins helps.
But sometimes you do want contextual modifiers, for example styling all components differently when they're in a certain type of container. For example, if the container's background is light grey, we'll want all nested text to have a subtle bevel (ie., white text-shadow).
It's tempting to use cascading for this, but that breaks — by definition! — separation of concerns. In one way it's better to actually have each component be container-aware; for example, given that Form and SpecialContainer are both components you can do this in form.scss:
.SpecialContainer {
background: #f0f0f0;
}
.Form {
.SpecialContainer & {
text-shadow: 0 1px 0 #fff;
}
}
It's cheating, though; now you have a dependency between the Form and SpecialContainer that really wasn't needed. So when I'm not being lazy, I resort to explicit parameters:
.Form {
&[data-light-background="true"] {
text-shadow: 0 1px 0 #fff;
}
}
Now I have to pass "lightBackground" as a prop to the component have it set the data-light-background attribute. Of course, this only works the component embedding Form actually knows that it has a light background or is embedded in one that has a light background. Not ideal.