Simple Sass BEM inheritance for modifiers - sass

I know this seems like a basic question, but despite all the great writings about sass and bem I'm missing how this inheritance works with nesting. Maybe someone here can clarify.
For example, a simple nav with links and active links:
.Header {
padding: 1rem;
&__nav {
display: flex;
align-items: center;
&-link {
#include fonts.bold;
font-size: 1.15rem;
&--active {
color: red;
}
}
}
}
And then this component:
const NavLink = props => (
<Link
{...props}
getProps={({ isCurrent }) => ({
className: isCurrent ? "Header__nav-link--active" : "Header__nav-link",
})}
/>
);
const Header = () => {
return (
<header className="Header">
<div className="Header__nav">
<NavLink to="/app/A">PAGE A</NavLink>
<NavLink to="/app/B">PAGE B</NavLink>
<NavLink to="/app/C">PAGE C</NavLink>
</div>
</header>
);
};
PROBLEM
Links that are not active - Header__nav-link get the font settings but the --active link does not. Is the "correct" way to do this by adding the base class to the markup along with active?
Like this: className="Header__nav-link Header__nav-link--active"

Yes, the correct way is what you described. Modifiers in BEM are intended to be used with a block class to alter it in some way from the base. If you think about it, a modifier class cannot be by itself because it has no defined block to modify.

Related

Angular 9 / SCSS not applied only for a child of a custom tag

I´m trying to work on my own angular library which was compatible for Angular 4.
My goal is to make it compatible for Angular 9.
For some reason, css is not applied for a child of a component. This component is the last nested component.
HTML output
<ui-label _ngcontent-nln-c13="" _nghost-nln-c12="" ng-reflect-label="test">
<span _ngcontent-nln-c12="">test</span>
</ui-label>
label.component.scss
foo-label {
//font-style: italic; //<-- works here :/
> span{
font-style: italic; //<-- not applied
}
}
Someone has got an idea ?
I found why it´s not applied.
It´s due to a scope component.
foo-label was wrapped by foo-tag like this :
<foo-tag _ngcontent-han-c14="" _nghost-han-c13="" ng-reflect-label="test" ng-reflect-hlevel="1">
<h1 _ngcontent-han-c13="">
<foo-label _ngcontent-han-c13="" _nghost-han-c12="" ng-reflect-label="test">
<span _ngcontent-han-c12="">test</span>
</foo-label>
</h1>
</foo-tag>
And the style was written in tag.component.scss.
like this :
tag.component.scss
:host{
> h1 {
> foo-label { //<--applied css until here !
> span {
...
}
}
}
}
You can fix with ::ng-deep like this :
:host{
> h1 {
::ng-deep > foo-label {
> span {
...
}
}
}
}
Works with mixin as well like this :
:host{
> h1 {
#include h($light-color, $title-header-size, $application-toolbar-icon-size);
}
}
#mixin h($text-color, $font-size, $size-img){
margin-top: 0;
margin-bottom: 0;
flex-shrink: 0;
white-space: nowrap;
::ng-deep > foo-label {
#include label($text-color, $font-size, $size-img);
}
}

Vaadin flow: grid conditional background color

I want to color grid lines, depending on a condition.
I try this:
Java:
gridEtudiant.setClassNameGenerator(t -> {
if (t.getEtud_numero().startsWith("2")) {
return "error_row";
}
return "";
});
Css:
td.error_row {
background-color: red;
}
HTML
<td id="vaadin-grid-cell-1" tabindex="0" role="gridcell" part="cell body-cell" first-column="" reorder-status="undefined" aria-selected="false" class="error_row" style="width: 100px; flex-grow: 1; order: 10000000;"><slot name="vaadin-grid-cell-content-1"></slot></td>
We can see the 'class="error_row"' but it's not colored in red.
Vaadin version is 13.0.1
Your java code looks good.
Make sure you have a html file like webapp/frontend/styles/shared-styles.html containing something like:
<dom-module id="my-grid-theme" theme-for="vaadin-grid">
<template>
<style>
[part~="cell"].error_row {
background: red;
}
</style>
</template>
</dom-module>
If you then have your Layout containing the grid annotated with #HtmlImport("frontend://styles/shared-styles.html") (which you already seem to have as your custom css class is already applied) it should work.
Example:
grid.addColumn(Customer::getFirstname).setHeader("Firstname");
grid.addColumn(Customer::getLastname).setHeader("Lastname");
grid.addColumn(Customer::getEmail).setHeader("Email");
grid.setClassNameGenerator(customer -> {
if (customer.getFirstname().equals("Marco")) {
return "error_row";
} else {
return "";
}
});
becomes:

How to select nth-child inside Element BEM Scss

I am using BEM Scss explain please how to select inside nth-child element.
I tried below format but it didn't work for me
<div class="bookearly-container" >
<div class="row bookearly-container__row">
<div class="col-xs-12 col-md-4 bookearly-container__col">
<div class="bookearly-container__discountcontainer">
</div>
<div class="bookearly-container__discountcontainer">
</div>
<div class="bookearly-container__discountcontainer">
</div>
</div>
</div>
</div>
MY BEM Scss I added nth-child 3rd element children element that is not working:
.bookearly-container {
&__row {
margin-bottom: 4.6rem;
& > :nth-child(3) {
&__discountcontainer { -- this element not selected
&:before {
display: none;
}
}
}
}
}
Can you please explain how to select? Thanks in advance.
You are using the child combinator (>) inside .bookearly-container__row(line 4 in your CSS example), and the only direct child there is .bookearly-container__col.
If you want to target the .bookearly-container__discountcontainer elements you need to adjust the selector nesting a bit.
Try using the #debug directive combined with the & selector to see what you are actually selecting, it's helpful when you get no other clues.
This is a straight-forward suggestion to solve it:
.bookearly-container {
#debug &; // .bookearly-container
&__row {
#debug &; // .bookearly-container__row
}
&__discountcontainer:nth-child(3) {
#debug &; // .bookearly-container__discountcontainer:nth-child(3)
&:before {
#debug &; // .bookearly-container__discountcontainer:nth-child(3):before
}
}
}
If you are depending on the child combinator (>) for some reason, you could nest it inside a &__col selector, like so:
.bookearly-container {
&__col {
// Targeting any class ending with "__discountcontainer"
& > [class$="__discountcontainer"]:nth-child(3) {
&:before {
#debug &; // .bookearly-container__col > [class$="__discountcontainer"]:nth-child(3):before
}
}
}
}

Angular 2 *ngFor with algorithm

I have a 'masonry' like grid on my website, which I display using *ngFor.
The grid blocks looks like the follow:
T T T
S A S
T S T
where T - stands for Tall blocks, S - short blocks, A - special section with a tall blocks height.
I'm trying to create a a grid which will be automatically populated using ngFor but using the grid schema.
For example:
T T T
S T S
T S T
and continue following the format ->
T T T
S T S
T S T
T T T
S T S
T S T
T T T
S T S
T S T
and so on, using the first three rows as an example, tall or short blocks specified by class only. So my questions is, which is the best way to check all this conditions in order to display them in the following format?
To get the effect you want, you will need to leverage css to create a masonry layout.
The best way is to use css column-count, but you will need to transpose your array so that each row of your data represents a column.
This example utilises ngClass to provide an object where the keys are CSS classes that get added when the expression given in the value evaluates to true.
masonry.component.ts
export class MasonryComponent {
wall = [['T', 'T', 'T'], ['S', 'A', 'S'], ['T', 'S', 'T']];
constructor() { }
transpose(arr: any[]){
return arr.map((col, i) => arr.map((row) => row[i] ));
}
}
masonry.html
<div class="wall" >
<ng-container *ngFor="let blockCol of transpose(wall)">
<div *ngFor="let block of blockCol" class="block" [ngClass]="{
'tall' : block === 'T',
'short': block === 'S',
'special': block === 'A' }">{{ block }}</div>
</ng-container>
</div>
masonry.css
.wall {
width: 170px;
column-count: 3;
}
.block {
width: 50px;
border: 1px solid black;
}
.tall { height: 50px; }
.special { height: 50px; }
.short { height: 25px; }

SCSS first-child & last child

Want to rotate one image to left, and then the other one to the right.
Something I really can't figure out why, the first part using last-child doesn't work, while the second works, any idea what the problem is?
Thanks!
<div>
<img scr="pic-a.jpg"></img>
<img scr="pic-b.jpg"></img>
</div>
img {
width: 45%;
transform: rotate(7deg);
&:last-child {
transform: rotate(-7deg);
}
}
/* the above doesn't work */
img {
width: 45%;
transform: rotate(-7deg);
&:first-child {
transform: rotate(7deg);
}
}
/* this works */
There must be something else messing up your code, as I tried to reproduce your error, it seems to work for me in both ways. Try it yourself.
One thing I also noticed was that your HTML is invalid. Your src attribute is misspelled and you don't need a closing img tag.
<div>
<img src="http://i.imgur.com/AzeiaRY.jpg"/>
<img src="http://i.imgur.com/AzeiaRY.jpg"/>
</div>

Resources