3

A codepen code (http://codepen.io/msisto/pen/lCofE) is displaying proper animations when it is run in Chrome but NOT showing properly when I open it in Mozilla Firefox. Is anything missing in the code chunk or do I need to include any strings to get the code work in Mozilla?

The CSS code is as below:-

// Customize
$option-color: #cbd1d8;
$checked-option-color: #40e0d0;
$option-size: 40px;
$explosion-distance: 5; // Multiplied by $option-size
$explosion-duration: 0.65s;

// On-click animation
@include keyframes(click-wave) {
$offset: ((($option-size*$explosion-distance)-$option-size)/2);

0% {
@include size($option-size);
opacity: 0.35;
position: relative;
}

100% {
@include size($option-size*$explosion-distance);
margin-left: -$offset;
margin-top: -$offset;
opacity: 0.0;
}
}

// Checkbox/Radio replacement
.option-input {
@include appearance(none);
@include position($option-size/3 0 0 0);
@include size($option-size);
@include transition;
background: $option-color;
border: none;
color: #fff;
cursor: pointer;
display: inline-block;
outline: none;
position: relative;
margin-right: 0.5rem;
z-index: 1000;

&:hover {
background: darken($option-color, 15%);
}

&:checked {
background: $checked-option-color;

// The checkmark
&::before {
  @include size($option-size);
  @include position(absolute);
  content: '\2716';
  display: inline-block;
  font-size: $option-size/1.5;
  text-align: center;
  line-height: $option-size;
 }

 // The "wave"
 &::after {
  @include animation(click-wave $explosion-duration);
  background: $checked-option-color;
  content: '';
  display: block;
  position: relative;
  z-index: 100;
  }
  }

  &.radio {
  border-radius: 50%;    

  &::after {
  border-radius: 50%;
  }
  }
  }

  // Demo styles
  body {
  @include box(horizontal, start, stretch);
  background: #e8ebee;
  color: darken($option-color, 15%);
  font-family: $helvetica;
  text-align: center;

  div {
  padding: 5rem;
  }

  label {
  display: block;
  line-height: $option-size;
  }
  }
Pointy
  • 405,095
  • 59
  • 585
  • 614
Sandeep
  • 49
  • 1
  • 1
  • 3

1 Answers1

1

Why?

The problem stems from the pseudo elements on the input tag; because they are void elements they are technically not allowed pseudo elements (which are technically children). Chrome works because it doesn't strictly follow the rules, Firefox displays the correct behaviour.

To make this clear, this is what ::before and ::after looks like on a div:

<div>
  <span>I am :before</span>
  I am content of div
  <span>I am :after</span>
</div>

it creates two children inside it. This is impossible with input as it cannot have children.

Here is another question I answered which had the same problem and has the same solution.

Solution?

  • Create the checkbox replacement with the label element itself. The label is connected to its corresponding input with the matching for and id attributes.

  • When the input is checked, it's corresponding label is targeted with input:checked + label to select only the immediate label following the input

  • The actual label text is placed in a span so that it can be pushed outside your checkbox

It looks like this:

<input id="check-one" type="checkbox" class="option-input checkbox" CHECKED />
<label for="check-one"><span>Hello</span></label>

Working Example

This is not perfect and will need to be tweaked; this is just to give you the general idea.

Here is your new codepen and the demo in vanilla CSS is below:

input[type=checkbox],
input[type=radio] {
  display: none;
}
@-webkit-keyframes click-wave {
  0% {
    height: 40px;
    width: 40px;
    opacity: 0.35;
    position: relative;
  }
  100% {
    height: 200px;
    width: 200px;
    margin-left: -80px;
    margin-top: -80px;
    opacity: 0.0;
  }
}
@-moz-keyframes click-wave {
  0% {
    height: 40px;
    width: 40px;
    opacity: 0.35;
    position: relative;
  }
  100% {
    height: 200px;
    width: 200px;
    margin-left: -80px;
    margin-top: -80px;
    opacity: 0.0;
  }
}
@keyframes click-wave {
  0% {
    height: 40px;
    width: 40px;
    opacity: 0.35;
    position: relative;
  }
  100% {
    height: 200px;
    width: 200px;
    margin-left: -80px;
    margin-top: -80px;
    opacity: 0.0;
  }
}
.option-input + label {
  -webkit-appearance: none;
  -moz-appearance: none;
  -ms-appearance: none;
  -o-appearance: none;
  appearance: none;
  position: relative;
  top: 13.33333px;
  right: 0;
  bottom: 0;
  left: 0;
  height: 40px;
  width: 40px;
  -webkit-transition: all 0.15s ease-out 0s;
  -moz-transition: all 0.15s ease-out 0s;
  transition: all 0.15s ease-out 0s;
  background: #cbd1d8;
  border: none;
  color: #fff;
  cursor: pointer;
  display: inline-block;
  outline: none;
  position: relative;
  margin-right: 0.5rem;
  z-index: 1000;
}
.option-input + label span {
  position: absolute;
  left: 100%;
  color: #000;
  margin-left: 10px;
}
.option-input + label:hover {
  background: #9faab7;
}
.option-input + label.radio {
  border-radius: 50%;
}
.option-input + label.radio::after {
  border-radius: 50%;
}
.option-input:checked + label {
  background: #40e0d0;
}
.option-input:checked + label::before {
  height: 40px;
  width: 40px;
  position: absolute;
  content: '\2716';
  display: inline-block;
  font-size: 26.66667px;
  text-align: center;
  line-height: 40px;
  left: 0;
}
.option-input:checked + label::after {
  -webkit-animation: click-wave 0.65s;
  -moz-animation: click-wave 0.65s;
  animation: click-wave 0.65s;
  background: #40e0d0;
  content: '';
  display: block;
  position: relative;
  z-index: 100;
  pointer-events: none;
}
body {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: box;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  box-orient: horizontal;
  -webkit-box-pack: start;
  -moz-box-pack: start;
  box-pack: start;
  -ms-flex-pack: start;
  -webkit-box-align: stretch;
  -moz-box-align: stretch;
  box-align: stretch;
  -ms-flex-align: stretch;
  background: #e8ebee;
  color: #9faab7;
  font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
  text-align: center;
}
body div {
  padding: 5rem;
}
body label {
  display: block;
  line-height: 40px;
}
<div>

  <input id="check-one" type="checkbox" class="option-input checkbox" CHECKED />
  <label for="check-one"><span>Hello</span>
  </label>

</div>
<div>

  <input id="radio-one" type="radio" class="option-input radio" name="example" />
  <label for="radio-one" class="radio"><span>Hello</span>
  </label>
</div>
Community
  • 1
  • 1
misterManSam
  • 24,303
  • 11
  • 69
  • 89
  • Just to be sure I get it: you're saying that the problem is with the `::before` and `::after` rules having no `content` property? – Pointy Nov 07 '14 at 13:45
  • @Pointy - no, the problem is caused because `::before` and `::after` cannot be placed on void elements, such as ``. Chrome is technically **incorrect** when it renders the CSS in the question. – misterManSam Nov 07 '14 at 13:47
  • Note that there is no closing slash for the input element. – Rob Nov 07 '14 at 14:00
  • @Rob - what do you mean? A void element can be self closed in HTML5, though it's not mandatory. – misterManSam Nov 07 '14 at 14:02
  • @misterManSam Yes. You can put the unnecessary and ignored and useless closing slash there if you wish but it makes no sense to do so. – Rob Nov 07 '14 at 14:03
  • @Rob - that comes down to personal preference. I learned in the days of XHTML and self-close by habit. To say there is "no closing slash" is just wrong and completely off-topic :-\ – misterManSam Nov 07 '14 at 14:05