Today I Learned

12 posts about #css

Fix for margin hell that affects your app container

Your app container has:

max-height: 100vh;

But your page still have a scroll

Whenever you hover over <body> you will see that it’s slightly off the top of the page. Suprisingly it has also margin: 0; The problem is that the children of your app container have some margins and it’s too much work the get rid all of them.

To fix the issue add to your app container:

display: flow-root;

grid/table/flex also works but only the flow-root keeps the block behaviour.

NOTE It doesn’t work on IE and some other browsers you don’t care about :)

Test it out: Link

SVG icons in pseudo-elements

For adding icons into css pseudo-element you need to set some size and content with SVG. Ie:

.icon-one:after {
    content: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm0 18c-4.4 0-8-3.6-8-8s3.6-8 8-8 8 3.6 8 8-3.6 8-8 8zm3.9-11.7L10 14.2l-1.9-1.9c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l2.6 2.6c.4.4 1 .4 1.4 0l6.6-6.6c.4-.4.4-1 0-1.4-.4-.4-1-.4-1.4 0z"/></svg>')

    display: inline-block;
    height: 20px;
    width: 20px;
}

But using this we’re not able to change the color of this SVG (icon). Property color or fill will not work.. :(

First idea

There is the second option of using SVG in pseudo-element, but this will not work on IE because it is not supporting mask-size property:

.icon-two:after {
    content: '';
    -webkit-mask: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm0 18c-4.4 0-8-3.6-8-8s3.6-8 8-8 8 3.6 8 8-3.6 8-8 8zm3.9-11.7L10 14.2l-1.9-1.9c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l2.6 2.6c.4.4 1 .4 1.4 0l6.6-6.6c.4-.4.4-1 0-1.4-.4-.4-1-.4-1.4 0z"/></svg>') no-repeat 50% 50%;
    mask: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zm0 18c-4.4 0-8-3.6-8-8s3.6-8 8-8 8 3.6 8 8-3.6 8-8 8zm3.9-11.7L10 14.2l-1.9-1.9c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l2.6 2.6c.4.4 1 .4 1.4 0l6.6-6.6c.4-.4.4-1 0-1.4-.4-.4-1-.4-1.4 0z"/></svg>') no-repeat 50% 50%;
    -webkit-mask-size: cover;
    mask-size: cover;
    
    display: inline-block;
    height: 20px;
    width: 20px;
}

For changing color we’re using background-color property.

.icon-two:after {
    background-color: red;
}

Second idea

SASS - Comments indent matters

As you might know, SASS has pretty nice nesting feature:

.selector
  color: red
  font-size: 12px

and SASS allows you to put comments, but beware of your comment indent because:

This looks completely fine in this IDE right?!

Yeah… but how does compiler see that?

… Boom!

.dark-theme
 // variables 
  @import 'base/dark-variables'

 // fonts
  @import 'fonts/dark'

Sass stylelint

Adding stylelint on the project (using ie RM) in a few steps:

First, you need to install a package: yarn add stylelint.

Second, you need to install a package with config for stylelint. For SASS it is yarn add stylelint-config-sass-guidelines

Third, you need to add to the project file .stylelintrc.json with some config, ie:

{
  "extends": "stylelint-config-sass-guidelines",
  "rules": {
    "block-opening-brace-space-before": null,
    "color-hex-case": "upper",
    "declaration-block-trailing-semicolon": "never",
    "max-nesting-depth": 5,
    "number-leading-zero": null,
    "scss/percent-placeholder-pattern": ".",
    "scss/selector-no-redundant-nesting-selector": "allow",
    "selector-class-pattern": ".",
    "selector-no-qualifying-type": null,
    "selector-pseudo-element-colon-notation": "single"
  }
}

PS. For Scss I created config here.

The last step :) You need to run this on your IDE (or run it in the terminal by hand). Structure stylelint in RM #1

Gray gradients on Safari

On Safari browsers gradients that includes transparent color might seem to be more gray(ish) than on other devices:

Typical look: Typical look

IOS mobile: Gray Safari look The mid part seems to be gray instead of light red.

So you have styles as follows:

.a {
  background-image: linear-gradient(#f00, transparent);
}

.b {
  background-image: linear-gradient(#f00, rgba(0,0,0,0));
}

.c {
  background-image: linear-gradient(#f00, #00F0);
}

.d {
  background-image: linear-gradient(#f00, #f000);
}

Which result on desktop is: Desktop elements

But on IOS mobile devices: Safari elements

As you might have already noticed, IOS cuts out the alpha part from color and use it like a mid-gradient part.

In case A and B it would be #000 (black)

In case C it would be #00F (blue)

In case D it would be #F00 (red) which is a result we expected from the beginning.

Codepen if you want to test it on your own: Link

About using & in nested selectors with BEM

In normal SCSS/SASS file code:

.calendar-container--theme-third {
  .calendar-reservation {
    &__checkout-wrapper:not(&--modifier):before {
      content: 'abc';
    }
  }
}

will be parsed to:

.calendar-container--theme-third .calendar-reservation__checkout-wrapper:not(.calendar-container--theme-third .calendar-reservation--modifier):before {
  content: 'abc';
}

so when U need to use ie. not with ampersand U will get the whole parent selector

:not(.calendar-container--theme-third .calendar-reservation--modifier)

instead of the last parent in & place

:not(.calendar-reservation--modifier)

For this situation, I created plugin/mixin: BEM-parent-selector

This mixin gives you an option to add selector only for the last parent.

.calendar-container--theme-second-2 {
  .calendar-reservation {
    @include BEM-parent-selector('&__checkout-wrapper:not(&--modifier):before') {
      content: 'abc';
    }
  }
}

will be parsed to:

.calendar-container--theme-second-2 .calendar-reservation__checkout-wrapper:not(.calendar-reservation--modifier):before {
   content: 'abc';
 }

How to Share Variables Between Javascript and Scss/Sass

When you need to share variables between javascript and scss/ sass you can export variables in your style file:

$calendar-min-width: 80px;
$animation-length: 250ms;
$animation-length-ms: $animation-length + 10ms;

:export {
  calendarMinWidth: $calendar-min-width;
  animationMillis: $animation-length-ms;
}

and after that you’re able to get this in javascript:

const variables = {
  calendarMinHeight: parseInt(styles.calendarMinHeight),
  animationMillis: parseInt(styles.animationMillis),
};

A way to make autofilled inputs background transparent

Consider the following form

form

There’s an issue with that form - If it’s filled with chrome-stored credentials - it looks like this

filled_ugly_form

Here’s the selector for autofilled input: input:-webkit-autofill

It’s possible to change color of this box, like this:

input:-webkit-autofill,
input:-webkit-autofill:hover, 
input:-webkit-autofill:focus, 
input:-webkit-autofill:active  {
  -webkit-box-shadow: 0 0 0 30px red inset;
}

But this method is not useful, if you want to make the background transparent.

However there’s a way (or rather workaround) to make it transparent, like this:

input:-webkit-autofill,
input:-webkit-autofill:hover, 
input:-webkit-autofill:focus, 
input:-webkit-autofill:active  {
  transition: background-color 5000s;
  -webkit-text-fill-color: #fff !important;
}

This is basically equivalent to transparent background, unless you’ll wait really long for the animation to complete ;)

SASS / BEM - Not TIL but still some interesting magic

Case 1 - we don’t want to write parent classname again from deep nesting

.some-class
  $this: &

  &.--sub
    margin-top: 2.4rem
    #{$this}__title // so it is .some-class__title
      font-size: 1.7rem

equals:

.some-class.--sub
  margin-top: 2.4rem
.some-class.--sub .some-class__title
  font-size: 1.7rem

Case 2 - we want to have a (or any another tag) before parent class from deep nesting

.btn
  margin-top: 2.4rem
  @at-root a#{&} // so it is a.btn
    font-size: 1.7rem

equals:

.btn
  margin-top: 2.4rem
a.btn
  font-size: 1.7rem