Using BEM CSS with Angular Directives - css

I've been using BEM style CSS to style my angular directives and usually use replace: true to so that my Block level class can be on the "root" of the custom element. This makes it so that I can write all my CSS primarily with classes.
However, replace: true sometimes causes issues (having two ng-if, etc...) and is now marked as deprecated. So I'm starting to try to stay away from replace completely.
But now I'm having trouble applying BEM to these elements that have an actual custom tag the DOM -- now I have to use a tag name instead of a class name, which means I can't really use BEM anymore (since I'll have to use the tag name since I can't apply classes directly to my element in my template). Additionally, using modifiers on my custom element now seems impossible, as does using sibling CSS selectors.
Here's an example that hopefully will illustrate what I mean:
The directive:
angular.module('my.module')
.directive('customElement', function() {
return {
restrict: 'E',
scope: {
isSpecial: '='
},
template: '<div class="custom-element" ng-class="{\'custom-element--special\': isSpecial"></div>'
};
});
The CSS:
.custom-element {
background-color: white;
}
.custom-element--special {
background-color: red;
}
.custom-element--special + .custom-element--special { // this won't work without replace: true
background-color: blue;
}
If I use replace: true everything works as expected (but then it comes with its own headaches).
If I don't use replace, the classes are not applied to the root custom element so the child selector doesn't work.
I could always add classes to the element in the postLink function, but that makes the template much less clear.
Does anyone have any experience using BEM with angular and using classes instead of tag names in your custom directives? What did you do to solve this problem?

i known it's a problem having replace:false for readability purpose.
The actual problem is that we need our OOCSS but you are handling Angular Components with custom tags has CSS Objects, and is not the case.
There is no practical solution for this, i won't recommend you to start adding classes on postLink function.
However what we are use to do is treat the custom tag as is own CSS Object besides the inner object structure. Forcing us to implement an extra CSS class for the custom tag.
block-context
block-context__element
custom-element
Why doing this when block-context__element is a redundant' class?
Because the rest of your BEM structure is the one you will maintain, the custom-element block should have meaning by it self and the block-context__element element is no expected to, you should abstract the CSS Objects from the directive's implementation, if you in some point start changing your html components your classes should still apply.
I hope this answer helps you

Related

Using css variable with styled-compoents

I know you can wrap your react app with <ThemeProvider /> and you can set a variable for the theme and access it like so:
const Text styled`
color: ${((props) => props.theme.red)};
`
But it's it CSS itself have the variable feature?
You can just do
:root {
--red: tomato;
}
.text {
color: var(--red);
}
is it ok to mix them? or stick to either styled-components or CSS?
Yes it is OK. Those 2 technologies have nothing to do with each other and are not conflicting.
As long as your components can inherit the CSS variables (AKA custom properties) they will work.
Just make sure they are really inherit.
Clearly defining variables on the root element selector (html) will make them available everywhere, but sometimes you don't want global variables, but more local, per page/area/component, so you need to structure you code taking that into account.
The real power of CSS variables is in their inheritance (unlike SCSS variables which are injected/replaces during the build-process).
The power of styled-components is isolation & the ability to share code with javascript. This does hinder their ability to inherit CSS variables defined at parents-level.
You need not bother yourself with this question at all, and simply ignore the fact you are using styled-components. All that matters is the HTML structure, which how inheritance works.
I Googled things for you:
https://medium.com/fbdevclagos/how-to-leverage-styled-components-and-css-variables-to-build-truly-reusable-components-in-react-4bbf50467666
https://betterprogramming.pub/7-ways-to-inherit-styles-using-styled-components-69debaad97e3
https://dev.to/arnonate/using-css-variables-to-tame-styled-component-props-2f9o

Reactjs, Bem naming nested structure with SCSSModule

We are using SCSS, SCSSModule and BEM naming methodology. I have researched the best structure for nested elements. I've seen different syntaxes and still have question mark in my head. I saw the symbol differences, for example some teams use "block__element_modifier", some use "block__element--modifier". I know basic usage of BEM. We shouldn't nest the elements with multiple underscored syntax(block__element__nested is wrong). Currently we are using BEM like
block__element--modifier
and nested elements are written with extra hyphen prefix.
Think that the card component structure like below
card
----header
----------title
----------subtitle
----body
----footer
and we code the sass like
// example.scss
.card {
&__header {
// some css
&-title {
// some css
}
&-sub-title {
// some css
}
}
}
and its classes' output is:
card
card__header
card__header-title
card__header-subtitle
Most of the answers in stackoverflow and also some of articles don't suggest BEM as above. They suggest like this:
.card {
&__header {
// some css
}
&__title {
// some css
}
&__sub-title {
// some css
}
}
and its output turn into this:
card
card__header
card__title
card__subtitle
But If I apply as in option 2, I can't figure out which element is in which when I only read scss file. On the other hand, we can understand that in the first option. But the disadvantage of the first option is that the elements become more dependent on each other. For example, when a new div comes between nested elements, I need to refactor related nested class names in the jsx file.
(But still think that it is very useful to understand which elements are nested in the scss file.)
The question is, is my BEM naming wrong or is there such a use in community?
Note: I said we use "module.scss" but I didnt give example in that format. I know, I didnt want to confuse with camelCase things in js.
Your naming is not wrong; it works and it satisfies the BEM pattern; but personally I would not recommend it, and would instead recommend the popular approach.
Your current approach encodes the DOM nesting of elements into the class names. If you need to make changes with regard to the nesting -for example you need an additional wrapper somewhere, which from my experience is a rather common occurence- you will need to change all nested class names. I would be immensely annoyed by that.
And a second drawback of your current approach is that it produces rather long class names.
But what I think is really the biggest drawback of it:
It forces you to nest your SCSS exactly like the DOM nesting to be able to build up the class names. This -in my opinion- makes the SCSS unnecessairily complicated.
With the popular approach your nesting depth for the styles can stay shallow and therefore easier to handle by humans, without messing up the braces { } or needing to nest and unnest rules when the DOM structure changes.
In one of my projects we started with your approach and later changed to the popular approach, and I experienced it as an improvement.
One example:
<div className="card">
<div className="card__header">
<div className="card__branding">
<Logo className="card__logo" />
<span className="card__brandname">Nutrax</span>
</div>
<h2 className="card__title">Recommendation for hard working web devs!<h2>
<div>
<div className="card__body">
Try Nutrax for Nerves!
<div>
<div className="card__footer">
<Button className="card__button">Find nearest store</Button>
<Button className="card__button card__button--promoted">Buy online</Button>
<div>
</div>
.card {
&__header {}
&__body {}
&__footer {}
&__branding {}
&__logo {}
&__brandname {}
&__title {}
&__button {
&--promoted {}
}
}
Now move the branding into the body, no problem, the changes are minimal, and you don't even need to change the SCSS.
PS: You mentioned that you use SCSSModules; I'm not sure I understand what that means. I'm well aquainted with css-modules and I use them usually in my react projects, which completely removes the need for BEM and I can just use rather simple class names that will be automatically scoped to my component only.
If that is also the case with SCSSModules in your project I don't see the need to apply BEM.

Ember: How to apply different stylesheets depending on the language?

I want to create an Ember application with two languages: one of them is rtl and the other is ltr.
How can I create two different stylesheets that one will loaded when I need rtl and one will loaded when I need ltr?
I'm using ember 2.8.
There are two main ways.
The first one - keep styles for different directions in different files and use only one of them. There is an obvious negative thing - you have to double your rules.
The second way - to keep it in the single way, but separate by css classes. Just add a language-related css class to the body, for example, .en or .th. Then modify your css for these classes:
div {
color: red;
}
.....
.th {
div {
color: blue;
direction: rtl;
}
}
If you select this way, I would encourage you to use a global lang attribute for the body tag instead of custom class names. It will make your css a little complex, but the semantic of your code will be perfect.

Inheriting CSS from existing styles. Extjs4 Sandbox

I have managed to embed my extjs4 panel inside an existing extjs3 application.
I want to inherit the existing css colour schemes for panel headers etc.
But my extjs4 components are 'sandboxed', therefore using the .x4-* namespace for css.
How can:
my-styles.css
.x4-tab { some-stuff }
inherit from:
existing-styles.css
.x-tab { foo: #FFF }
Is this possible? cheers
You can grab all the existing css rules that have '.x-' in the selector and create new rules using '.x4-'.
var newRules = [];
Ext.Object.each(Ext.util.CSS.getRules(), function(selector, rule) {
if (/\.x-/.test(selector)) {
newRules.push(rule.cssText.replace(/\.x-/g, '.x4-');
}
});
Ext.util.CSS.createStyleSheet(newRules.join(' '))
While this is technically possible to do, the results would not actually make sense unless you manually go through each component and override the classes to have the correct css references if they even exist (and you would have to create others manually). This is because Extjs 4 does not work the same way in a technical sense for css namespacing and classes as Extjs 3. You could manually change all the css classes the components are using by overriding their component classes, but this is just not worth the time. What you are trying to do can not be done without a huge amount of effort, and it is just not worth it.

Is it error-prone to use ID-attribute selectors (not #id) on body elements to namespace CSS files?

I'm using Sass to compile my SCSS stylesheets into a single assembled.css to reduce HTTP requests. To namespace individual pages for styling, I wrap each page-specific CSS file in an ID selector for that page's <body> element - for example:
body#support {
.introduction {
#extend %dropcap;
}
}
In nanoc (using ERB), I have a helper that assigns each page's body a dash-separated unique ID based on the HTML folder structure, so the root pages will be #support or #products, while their sub-pages would have an ID like `#products-giantspacelaser'.
I want to make a set of SCSS rules that only apply to these 'products' sub-pages (not including the root-level #products page itself). Is there anything I should look out for regarding specificity if I use an attribute selector instead of an ID for this, as follows?
body[id^="products-"] {
.introduction {
#extend %dropcap;
}
}
I really don't want to use !important, but I do want to ensure that these page-specific rules take precedent over styles set in the '_base.scss' partial that precedes them in the #import order. Seeing as I have full control over the HTML structure, I could also theoretically use Erb in the Sass files to substitute in a comma-separated list of IDs like so:
body#products-giantspacelaser,
body#products-laboratorycamouflage,
body#products-resurrecteddinosaur {
.introduction {
#extend %dropcap;
}
}
- but that seems quite inelegant. Thanks in advance.
EDIT:
I've written my other styles in a really cascade-reliant way:
Normalise CSS
HTML5 Boilerplate's & my own sensible house rules
CSS Libraries (in this case Bourbon & Neat)
A "_source.scss" which in turn imports its own mixins & placeholder selectors.
A "_base.scss" which styles the default layout framework of every page.
A series of .scss files for each page's individual content styling - and, I hoped, overrides of base.scss layout decisions when necessary (if the page needs to take a serious departure from the norm).
Either way, these individual page stylesheets would need to definitely have a higher specificity than earlier defaults, as they were written for a specific purpose & page.
I'm intentionally not using any ID selectors except for this one specific purpose - namespaceing page stylesheets.
Using, say
.services .sharktraining .introduction .disarmingJoke {} --0,0,4,0
in "_base.scss" would surpass
body[id^="products-"] .disarmingJoke {} --0,0,2,1
in a further-down-the-cascade "products.scss", wouldn't it? (N.B. I know needing to use four classes is awful practice, I just don't want to worry about something slipping through the namespace).
I suppose there's another - really dirty - option: to repeat the body[id^="products-"] selector many times, to simply outnumber even the most specific class-strength rule.
It's going to have to depend on how you've written your other styles and whether or not they should take precedence (see: http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/).
If you match the selector exactly but prefix one of them with your body selector, the prefixed one will be specific enough to take precedence no matter what (even if the order was reversed):
body[id^="products-"] .widget {
color: green;
}
.widget {
color: red;
}
The .widget will be green because the first selector is more specific than the second.
The only problem with using attribute selectors over ids is if you care about IE6. If that's a concern for you, the IE7 JS library by Dean Edwards can help you out: http://code.google.com/p/ie7-js/
If changing how the page information is attached to the body element is an option, my recommendation would be to have the parent directory be an id and the child pages be classes:
<body id="products" class="giantspacelaser" />
This way you can retain the specificity of the id:
// excludes the body#products page, which wouldn't have a class set at all
body[class]#products {
// styling here
}

Resources