5
votes

TL;DR - how can I nest validation states using a SASS mixin?

Long version -

I'm having a few difficulties using Bootstrap 4's SASS to generate a dark theme. Some variable replacements are obvious, but others are causing issues. The one I am currently stuck on is form inputs. Bootstrap's SASS will spit out white-background inputs by default. I override this background with a variable I have collected, and set the border to be 50% of the body's text colour (it will have contrast still, but not be stark).

At the time of compile (which is a dynamic process handed over to the back end), the compile engine "cannot" know if the theme is intended to be dark or not dark, so I leave it to the designer to add a "content-dark" class to a container that should have the dark theme (usually but not necessarily the body).

So far so good! Then it occurred to me that focus looked funny, because my more specific rule is enforcing my new border color over top of the SASS-calculated one. Including the whole "focus" mixin doesn't work because it reverts the background to white again. I locate the individual "bit" that does the work and move it into my new nested rule.

HOWEVER, the mixin for validation is much more complex, so I was willing to try out the full mixin... with the idea (unfortunately a bit convoluted) of letting it do its thing and then adjusting my background-color to be even more specific again (yay specificity war). However, my knowledge of SASS is dodgy and this isn't working:

.content-dark {
    select.form-control, .form-control {
        background-color: $nav-background;
        color: darken($body-color, 33%);
        border: 1px solid darken($body-color, 50%);
        &:focus {
            border-color: $input-focus-border-color;
        }
        @include form-validation-state("valid", $form-feedback-valid-color);
        @include form-validation-state("invalid", $form-feedback-invalid-color);
    }
}

The input background is correctly dark, the border is GENERALLY correctly a contrasting (but not bold) color, and focus is correctly a luminous blue. But validation states don't work. They're still not nested, meaning the border is not updating even if the "glow" is.

I'm looking for the best way to have dark-themed validation states (the nesting is required; a separate compile would solve the problem but I don't have that option).

1
To reiterate: I realize that all could be avoided if the original outline override and background weren't MORE specific due to the nesting. It's the higher specificity that's breaking stuff. - Greg Pettit

1 Answers

0
votes

Still interested in other answers, because the LIGHT themes end up looking janky (but at least they work) but this is what I did in the meantime:

I dropped the nested thing altogether since I KNEW that was the main problem, and declared these two variables in my _custom_variables.sass file:

$input-bg: $nav-background;
$input-border-color: darken($body-color, 50%);

It's dicey because $nav-background doesn't HAVE to be dark (when a dark theme) or light (when a light theme), so I will need to update the information I collect (something called "input border" and "input background" are obvious choices). This has the benefit of not needing the nesting, but the drawback of exposing more options in my theming interface (the idea was to make it streamlined).

[update]

So, after having to heavily curate the flood of answers, I ended up parameterizing the two things. Bootstrap plays mostly nicely with it now, in that state, and I have 2 more fields on my customization page form. Le sigh.