Inherit bootstrap properties to a custom class - css

I want my custom class pm_btn to get all the properties that bootstrap's btn class has. One way is to use the actual source code of the btn class. But I believe that there has to be a better way. Therefore, I tried a bit of scss, where inheriting properties is quite easy and trivial using #extend as follows:
.pm_btn{
#extends .btn;
}
But this throws error :
Error: The target selector was not found.
Use "#extend .btn !optional" to avoid this error.
I am trying to achieve: apply bootstrap like classes to django-postman classes.
Please suggest me how can I achieve this, if I am on the right track by choosing SCSS or should I think in some other directions. Thank you for your valuable time.

Not sure what your tooling setup is, but if it will allow it, Bootstrap has a Sass version you can use. This will allow you to extend bootstrap's functionality with your own custom classes.

You can use bootstrap sass files and #extends keyword to extend .btn class to your needs
or
more easily you can write a separate class along and modify its properties to suit your needs and you can call that style for reusability , For eg
.button--custom {
/* required properties here */
}
<button class="btn btn-primary text-light button--custom">my button</button>
You need to call in the given class order or it wont work

Related

Sass generated classes not getting applied

I have a custom sass setup with bootstrap 5 and bunch of my own SCSS files, all of this gets compiled in style.css using gulp. I have a _colors.scss file which stores all the colors according to our design language. We use this to generate a bunch of classes that can be used any where to change colors:
// Text Colors
$colors: (
"icon-color": $slate-500,
'slate-10': $slate-10,
'slate-40': $slate-40,
'slate-300': $slate-300,
"secondary": $secondary-text-color,
"green": $green,
"light-green": $green-color,
"blue": $blue,
"blue-200": $blue-200,
"blue-300": $blue-300,
"blue-400": $blue-400,
"dodger-blue": $dodger-blue,
"mariner-blue": $mariner-blue,
"light-blue": $blue-100,
"cadet-blue" : $cadet-blue,
"aqua-10": $aqua-10,
"gray": $gray,
"gray-light": $gray-light,
"light-gray": $gray-100,
"bright-gray": $bright-gray,
"gray-200": $gray-200,
"clay": $clay,
"clay-10": $clay-10,
"mandy-pink": $mandy-pink,
"aqua": $aqua,
"violet": $violet,
"white": $white,
"primary": $primary-text-color
);
#each $color-name, $color-value in $colors {
.text-#{$color-name} {
color: $color-value !important;
}
.bg-#{$color-name} {
background-color: $color-value !important;
}
.border-#{$color-name} {
border-color: $color-value !important;
}
}
Problem is certain classes like .text-gray or .text-blue are not working. My guess is that since bootstrap also uses variables called gray and blue, its conflicting with my variables in _colors.scss.
On closer look, the css does gets generated properly (I found below declaration in final style.css):
.case-study .case-study-right .card .data-bar p:last-of-type,.share .social-media>span,.text-color-gray-200,.text-gray-200 {
color: #69727A!important
}
But using .text-gray has no effect, the class is not getting applied.
How do I fix this? please help!
First, if you're sure that you see the correct selector and the correct rule in your CSS file: it should be applied. And so, the rule should be visible in the browser console (even if overridden).
If you see it in your CSS file, but not applied in the browser console: check that your CSS file is valid (and that your gulp production script compiles fine), as a bad character could mess some part of it.
If you see your CSS in the browser console, but it's overridden by some bootstrap rules, you can override bootsrap variables, and change bootstrap colors by yours like so (import bootstrap before this):
$theme-colors: (
primary: #121212,
success: #8bcea8
...
);
You could also try this to replace bootstrap values by yours:
$theme-colors: map-merge($theme-colors, $colors);
The simple answer is:
Use Bootstrap 5 the intended way!
Bootstrap is a complex framework. All that huge number of classes work together including overwriting color settings if provided and used the intended way. In your code example you additional create helper classes Bootstrap would provide to you out of the box if you use it the Bootstrap way. As you did not do it leads to conflicts which are not easy to handle ... and nearly impossible to solve without to have the possibility to analyize the page itself.
This is what you may check:
You may check: are there other classes which blocks your classes?
In your example you use !important to get higher specifity. But the color is overwritten by other classes ...
Maybe that are Bootstrap which uses !important as well. In that case you can try to add your classes at the end of your CSS (after the Bootstrap classes) so they are able to overwrite in case of identical specifity.
Additional: in your example you added a huge bunch of non-bootstrap-classes. Maybe this individual added classes blocks your styling by adding a color with higher specifity (using !important as well which is not a good technique at all) to your element than your added class do.
In that case same solution may be possible ... but individual classes with !important and an additional higher specifity (i.e. using two class names in the selector) will win over your helper classes also your helper class comes later in your CSS file.
To be honest: most often analyzing such an huddle of classes indeed is only possible in the browser on the page direct using the developer tools.
But best way indeed would be ...
Do a correct Bootstrap theming and use Bootstrap classes!!!
You really don't need to create the helper classes on your own. Just do a SASS setup of Bootstrap ... and add your needed/additional colors NOT (or not only) to map $colors but AS WELL TO Bootstrap map $theme-colors. Bootstrap builds up helper-/utility-/elements-color-classes not on $colors but on $theme-colors. That means: doing that this intended way ... all your helper classes you added in your project on your own will be provided by Bootstrap mechanic in the correct order and avoiding conflicts to your CSS.
Use Bootstrap classes to style your page. Now you don't need to create an additional class .case-study { color: gray }. Just use the Bootstrap helper class and add .text-gray to same element. (Note: In your example you use the incredible number of NINE classes to do the same styling. In case 'text in cards' here is a nice hint how to realize it the bootstrap way: https://getbootstrap.com/docs/5.0/components/card/#border).
Just thinking about using complex Framework...
Bootstrap is done to help you. As there is a lot of code using that Framework only makes sense to use the code as much as possible without writing new classes. So best way indeed to work with it is to use the Bootstrap elements and styling them the Bootstrap way. That makes it simple and avoids conflicts... And: you are able to do nearly everything with these elements.
And if you need to extend Bootstrap i.e. with additonal classes: avoid (deep) nested classes and !important as well so you are able to overwrite settings with simple helper classes.
i had the similar problem it was my scss was successfully converted to the css but not applied, after checking for hours i found out ,i have written B capital while the class name was btn
so when everything is working then the problem is always in your code syntax!

How to dynamically set complex CSS of an Angular 2+ component?

I'd like to ask for a little nudge to get my brain out of the box I got it into.
Context
Angular 4 using Angular CLI and AoT.
All methods mentioned in https://angular.io/docs/ts/latest/guide/component-styles.html describe ways to set complex CSS of a component while it is being written by a developer.
After a component is created, Angular allows to adjust individual styles and even assign various CSS class names to tags in the component as you please, all that using [ngClass], <div [class.something]="condition">, various #HostBinding decorators and some other methods.
However, none of the above can change the CSS declaration the component is using. The methods above can either (a) use what is already available in the stylesheet defined by the developer or (b) set individual CSS properties to individual HTML tags in the component's template.
Question
How would I update the CSS for the whole component on runtime so that all elements in that component respond to the new CSS?
Say I introduce a new style for a div.someClass and I want all matching elements div.someClass to reflect the new style.
Plunker
A showcase of my attempts is here: https://plnkr.co/edit/N2C40cSb7hd1AyOxWWdT
The button should be red, based on the value of MyChildComponent.styles
I think I understand why it doesn't work the way I would expect: shortly said, styles are built in the component during compilation, not runtime, including those found inside <style /> tags in the template.
But knowing why it doesn't work doesn't help me to make it work.
Any help highly appreciated.
Solution 1
Inserting a new css class is not possible ( as far as i know ) but you can insert css properties to your component dynamically.
I modified your dynamicStyles() to this
get dynamicStyles(): any{
return {'background': 'red' };
}
that returns an object instead of string because you will pass this object to ngStyle of your button.
In your template, I change the button like this
<button type="button"
[ngStyle]="styles">
Button
</button>
Here's a plunkr
Solution 2
This is something that I would not recommend but in your case it might be useful. You can add this
encapsulation: ViewEncapsulation.None
and the import
import {ViewEncapsulation} from '#angular/core'
to your #Component.You can leak your component's css so that you can use it on your child component. Then in your child component, add a [ngClass] in your button so that you can just pass a variable via #Input() if it should be red.
<button type="button"
[ngClass]="{'redButton': isButtonRed}"
>Button</button>
And in your style.css
.redButton{
background:red;
}
And in your main component.
<div>
<h2>Hello name</h2>
<my-child [isButtonRed]="true"></my-child>
</div>
Here's another plunkr
Hope this helps.

Using less.css and Twitter Bootstrap 3 - mixins not working

Alrighty, so I am trying to add classes to my page via css. Below is an example of the less.css file I am writing:
.someClass {
.col-sm-6;
}
I swear this worked before, but for whatever reason, my compiler throws an error:
".col-sm-6 is undefined"
Compiler: WinLess
Essentially I'm just trying to assign the col-sm-6 class to a div for width/float etc... Please let me know if you can think of any reasons this wouldn't work.
Thanks!
Bootstrap 3 makes these class names via a dynamic mixin, so they are not directly accessible as mixins themselves (dynamically generated class names are not currently able in LESS to be accessed as mixins). Instead, you need to call the mixin to generate the code by doing this:
.someClass {
.make-sm-column(6);
}

How to use sass to properly avoid embedding twitter bootstrap class names on HTML

I am working on a Rails project that is just starting. We want to use twitter bootstrap as a base for our styles, at the beginning we would simply use bootstrap's class names directly on the HTML code, just like is shown in bootstrap's documentation, but after reading the following posts:
Lessons learned in maintainable css
Please stop embedding Bootstrap classes in your HTML
it became clear why that's not the proper why to use bootstrap, so after some more readings:
Decouple Your CSS From HTML
smacss
among other, it seemed that using sass #extend was the proper way to avoid using bootstrap's class names, so instead of doing this:
<button type="submit" class="btn">Search</button>
we would do this:
<button type="submit" class="button">Search</button>
and our sass code would look like this:
.button {
#extend ".btn";
}
The problem with that approach, besides the bunch of extra selectors that will be added each time we extend a bootstrap class just to use a different name, is that in cases where bootstrap uses selectors like this:
.form-search .input-append .btn, .form-search .form-input-append .btn {
border-radius: 0 14px 14px 0;
}
the button won't get the right style because sass will not apply that same rule to our custom class name, I mean, sass is not doing this:
.form-search .input-append .btn, .form-search .input-append .button,
.form-search .form-input-append .btn, .form-search .form-input-append .button {
border-radius: 0 14px 14px 0;
}
So I wonder, is this the right way to avoid embedding bootstrap's class names into HTML, if so, how should I handle this problem (it happens frequently)? if not, what would be a better way to use custom class names but still get the styles from bootstrap.
I really appreciate your thoughts on this. Please keep in mind that I am just learning about overall web design (css, sass, less, html, js, etc.).
When you rename .btn to .button, you also should rename .form-search to .form-searchnew etc?
In that case your sass code in the example above should be something like:
.form-searchnew .input-appendnew .button {
extend(.form-search .input-append .btn);
}
Which make sense (i don't know sass) and results in the css you expect.
I think bootstrap is not about css only. Bootstrap is about css, html(structure) and javascript. Even when you separate css from html i would not easy to migrate to an other framework. Beside the css you will have to change the html structure and javascript call too.
Example migrate from Twitter's Bootstrap 2 to 3 (see: Updating Bootstrap to version 3 - what do I have to do?). I also wondered if you could migrate by extending the old classes to the new css (see: http://bassjobsen.weblogs.fm/migrate-your-templates-from-twitter-bootstrap-2-x-to-twitter-bootstrap-3/). After reading the migration guide, i think you couldn't.
Other solutions. Angular JS decouples Twitter's Bootstrap from javascript. Also in this case migrations does not seem to be painless see: Angular Dialog directives with Bootstrap 3
Maybe also read this post: http://www.jasonwong.org/post/45849350459/migrating-from-zurb-foundation-twitter-bootstrap-to. It refers to Bourdon and Neat.
Example from their website:
<!-- HTML markup for the section right below this code block -->
<section>
<aside>What is it about?</aside>
<article>Neat is an open source semantic grid framework built on top of Sass and Bourbon…</article>
</section>
// Enter Neat
section {
#include outer-container;
aside { #include span-columns(3); }
article { #include span-columns(9); }
}
// And the result is...
As they say: "it relies entirely on Sass mixins and does not pollute your HTML" which seems the way you're looking for.
I recommend you have a look at sass placeholder classes http://sass-lang.com/documentation/file.SASS_REFERENCE.html#placeholders in order not to bloath your css. Most likely you won't be using every single element included in bootstrap and placeholders only get written to your stylesheet if they are actually extended in your code.
Also, I think people tend to get confused about how css frameworks work and how decoupling css and html actually works.
For very large websites (or ones that you expect eventually to grow very large), where performance and css file size is crucial, some kind of OOCSS approach is your best bet. And this means inevitably that you have formatting code directly in your HTML.
If you can allow yourself to be a little less efficient and want your HTML clean, make sure to use semantic classes (examples for buttons: call-to-action, call-to-action-secondary, submit, btn-primary, btn-corporate-color, etc...)
Also remember to decouple your JS from CSS! use special classes for attaching behaviour (example js-submit, js-call-to-action, etc....)
Last but not least: don't plan for updating your css framework. These frameworks are meant to give you a headstart, not to be your overall design solution. Extend them, adapt them, make them your own, invest in design and create your own look in order to make your app unique.
If what makes you think of updating is a worry to keep up with standard changes, better use compass mixins.
Use #extend, but don't quote selectors:
.button {
#extend .btn;
}
Then you'll see that Sass extends related selectors too, like you want (.form-search .input-append .btn etc.).
… besides the bunch of extra selectors that will be added each time we extend a bootstrap class just to use a different name …
#extend works by copying selectors. If you don't want that, you can "extend" in HTML instead -- i.e. add Bootstrap's class names. :)
For being new to most of this, you're on the right track; the resources you've been reading are excellent. But, I think the concerns you have might not be justified:
...the button won't get the right style because sass will not apply that same rule to our custom class name...
In fact, I think you must be mistaken. According to the Sass documentation:
#extend works by inserting the extending selector (e.g. .seriousError) anywhere in the stylesheet that the extended selector (.e.g .error) appears.
See http://sass-lang.com/documentation/file.SASS_REFERENCE.html#how_it_works for the full code example.
Your original solution was actually correct. Use extends, but without the quotes:
.button {
#extend .btn; //no quotes
}
I tested this using your example, and it works correctly. Sass copies all the selectors with ".btn" and on those newly created selectors, it replaces ".btn" with ".button".
Also, if Sass produces too much duplication for your liking, don't worry about it (so long as you are following best practices as pointed out by the links you posted). Duplicate code is easily compressed if the server uses gzip or the equivalent; the client shouldn't notice any slower loading times, although it might take slightly longer to "unzip" the CSS. As for CSS selector speed, don't worry about that either; the only case where speed matters for selectors is on the JavaScript side, particularly with jQuery. For your Sass code, simply follow best practices for maintainability (notably, modularization as you are trying to do, i.e. SMACSS) and you'll be good to go.
The answers given by sam and tjklemz will help you resolve your immediate technical challenge, but it's possible to decouple your CSS and HTML even more. I'll give an example below, but keep in mind that this is just a quick example to demonstrate the power of mixins/extending CSS classes.
I'd also strongly recommend checking out the ZURB Foundation framework, as it is natively SASS, and designed with this style of development in mind.
For example:
<body>
<div id="my-header">
<h1>My Company</h1>
<h2>My Tagline</h2>
</div>
<div id="my-main">
<div class="my-widget">
<h1>Widget Title</h1>
<a>Widget Option 1</a>
<a>Widget Option 2</a>
</div>
</div>
</body>
With the accompanying SCSS:
//these examples wouldn't really work
//because bootstrap needs more markup
#my-header {
#extend .navbar;
}
#my-header h1 {
#extend .branding;
}
#my-main {
#extend .container;
}
//good example
.my-widget {
#extend .well;
#extend .hero-unit;
}
.my-widget a {
#extend .btn;
}

css class within another class as a property

I'm wanting to use properties from other css classes without having to rewrite the code...I'm not too savvy with css so please forgive me for the simple question.
Is it possible to do something like this or similar to it in css?
.class_a {
background:red;
}
.class_b{
.class_a;
}
The best way (that I know of) to re-use css classes is to decide on the css attributes you want to re-use, and put this in a seperate class, like so:
.class_a {
background:red;
}
Then, every time you want to re-use these attributes, you add the class to the html element, with spaces in between different class names, like so:
<div class="text class_a">This will be red, and have the properties of the text class</div>
<div class="text">This will only have the properties of the text class</div>
You can use the same property list for more than one selector:
.class_a, .class_b {
background:red;
}
There are CSS tools which allow you to code in the way you describe. You just do some post-processing of your code to produce valid CSS.
Check out LESS.
Not possible using CSS. However, you can achieve this using something like Sass. Sass allows you write CSS with enhancements such as the one you described. Unfortunately, this introduces an extra step since Sass files must be converted to CSS before you can use them on your page. Could help save you a lot of typing though :)

Resources