Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="notify bar-top do-show" data-notification-status="success">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure, reprehenderit obcaecati itaque. Officiis libero provident perspiciatis eum fugiat laudantium sequi.</div>

<main>
  <div class="wrapper">
    <h1>CSS-only Notifications Component</h1>

    <p>
      This is a Sass mixin that provides notifications functionality using little-to-none Javascript.<br> It makes use of CSS transitions and animations to display notifications as popups or bars on different locations of the viewport.<br> The best thing
      is that it is fully customizable and easy to use. :)
    </p>

    <nav>
      <a href="#" class="button" data-type="top-left" data-status="success">Top Left</a>
      <a href="#" class="button" data-type="top-right" data-status="warning">Top Right</a>
      <a href="#" class="button" data-type="bottom-right" data-status="error">Bottom Right</a>
      <a href="#" class="button" data-type="bottom-left" data-status="notice">Bottom Left</a>
      <a href="#" class="button" data-type="bar-top" data-status="plain">Top bar</a>
      <a href="#" class="button" data-type="bar-bottom" data-status="plain">Bottom bar</a>
    </nav>
  </div>
</main>
              
            
!

CSS

              
                ////
/// Notifications
/// @group components
/// @author Damián Muti
////

@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');

///
$notification-status: (
  'notice': (
    color: #29B6F6,
    icon: 'M11.016,6.984V9h1.968V6.984H11.016z M11.016,17.016h1.968v-6h-1.968V17.016z'
  ),
  'warning': (
    color: #FFCA28,
    icon: 'M11.016,17.016h1.968V15h-1.968V17.016z M11.016,6.983v6.001h1.968V6.983H11.016z'
  ),
  'error': (
    color: #EF5350,
    icon: 'M13.406,12l2.578,2.578l-1.406,1.406L12,13.406l-2.578,2.578l-1.406-1.406L10.594,12L8.016,9.421l1.406-1.405L12,10.593 l2.578-2.577l1.406,1.405L13.406,12z'
  ),
  'success': (
    color: #66BB6A,
    icon: 'M10.477,13.136l5.085-5.085l1.406,1.406l-6.492,6.492l-3.446-3.445l1.406-1.406L10.477,13.136z'
  ),
  'question': (
    color: #8D6E63,
    icon: 'M12.001,6.314h-0.002c-1.996,0-3.609,1.614-3.609,3.609h1.784c0-0.977,0.85-1.784,1.826-1.784  c0.977,0,1.827,0.807,1.827,1.784c0,1.826-2.718,1.614-2.718,4.544h1.784c0-2.038,2.717-2.294,2.717-4.544  C15.609,7.928,13.997,6.314,12.001,6.314z M11.109,17.186h1.784v-1.826h-1.784V17.186z'
  ),
  'plain': (
    color: #333
  )
);
///
$notification-toast-positions: (
  'top left': (
    top: 0,
    left: 0
  ),
  'top right': (
    top: 0,
    right: 0
  ),
  'bottom right': (
    bottom: 0,
    right: 0
  ),
  'bottom left': (
    bottom: 0,
    left: 0
  )
);
///
$notification-icon-size: 30px !default;
///
$notification-box-shadow: true !default;
///
$notification-show-icon: true !default;
///
$notification-toast-margin: 20px !default;
///
$notification-toast-max-width: 350px !default;
///
$notification-toast-total-width: $notification-icon-size + ($notification-toast-margin * 2) + $notification-toast-max-width;

@keyframes fade-in {
  from {
    visibility: hidden;
    opacity: 0;
  }

  to {
    visibility: visible;
    opacity: 1;
  }
}

@keyframes slide-show {
  to {
    transform: translateY(0);
  }
}

/// URL-encode color SASS function / convert color to hex SASS function.
/// @param {color} $color - Hex color value to convert.
/// @return {string} URL-encode color value.
@function encode-color($color) {
	@if type-of($color) == 'color' {
    $hex: str-slice(ie-hex-str($color), 4);
    $color: unquote("#{$hex}");
  }
  
  $color: '%23' + $color;
	
  @return $color;
}

/// Generates an SVG with a given fill color depending on the type of icon passed as parameter. The SVG string is scaped for cross-browser support.
/// @param {string} $icon - Type of icon. Accepted values: `quarter`, `half`, `three-quarters` or `full`.
/// @param {color} $color - Passes the fill color of the SVG icon that is being generated. Note: Hexa color values must be escaped for cross-browser support.
/// @return {string} background value.
@function get-icon($status, $icon, $color) {
  @return url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M12 3.984c4.407 0 8.016 3.609 8.016 8.016 0 4.406-3.608 8.016-8.016 8.016S3.984 16.407 3.984 12 7.593 3.984 12 3.984m0-2C6.478 1.984 1.984 6.477 1.984 12c0 5.521 4.493 10.016 10.016 10.016S22.016 17.522 22.016 12c0-5.523-4.495-10.016-10.016-10.016zm0 2c4.407 0 8.016 3.609 8.016' fill='" + encode-color($color) + "'/%3E%3Cpath d='" + map-get(map-get($notification-status, $status), $icon) + "' fill='" + encode-color($color) + "'/%3E%3C/svg%3E") center / cover no-repeat;
}

/// Component that shows two different types of notification boxes: toast and bar.
/// @param {string} $position ['bottom right'] - Positioning for each notification box. Accepted values: `top left`, `top right`, `bottom right` or `bottom left`.
/// @param {string} $type [toast] - Type of notification. Accepted values: `toast` or `bar`.
/// @param {string} $animation [slide] - Animation style to show the notification. Accepted values: `slide` or `fade`.
/// @param {number} $duration [1s] - Duration of the show/hide animation.
/// @param {number} $persistance [3s] - Visibility duration.
@mixin c-notification($position: 'bottom right', $type: toast, $animation: slide, $duration: 1s, $persistance: 3s) { 
    position: fixed;
    z-index: 1000;
    display: flex;
    align-items: center;
    padding: 20px;
    color: #fff;
    line-height: 1.3;
  
    @if($notification-box-shadow) {
      box-shadow: 0 0 15px 0 rgba(#000, 0.35);
    }
  
    @if $animation == fade {
      visibility: hidden;
      opacity: 0;
      
      &.do-show {
        animation: 
          fade-in $duration ease-in-out forwards, 
          fade-in $duration ease-in-out reverse forwards $persistance;
      }
    }

    // Toast type
    @if $type == toast {
      max-width: $notification-toast-max-width;
      margin: $notification-toast-margin;
      
      // Iterate through $notification-toast-positions map and generate the proper styling
      @each $pos, $coords in $notification-toast-positions {
        @if $pos == $position {
          $separator: str-index($position, ' ');
          $y: str-slice($position, 0, ($separator - 1));
          $x: str-slice($position, ($separator + 1));
          
          #{$y}: map-get($coords, $y);
          #{$x}: map-get($coords, $x); 
             
          @if $animation == slide {
            @at-root {
              @keyframes slide-in-#{$x} {
                to {
                  transform: translateX(0);
                }
              }
            }
            
            transform: translateX(if($x == left, #{'-'}, #{''})#{$notification-toast-total-width + map-get($coords, $x)});
            
            &.do-show {
              animation: 
                slide-in-#{$x} $duration ease-in-out forwards, 
                slide-in-#{$x} $duration ease-in-out reverse forwards $persistance;
            }
          }
        }
      }
    }
    @elseif $type == bar {
      #{$position}: 0;
      right: 0;
      left: 0;
      width: 100%;
      
      @if $animation == slide {
        transform: translateY(if($position == top, '-', '')100%); 
      
        &.do-show {
          animation: 
            slide-show $duration forwards, 
            slide-show $duration reverse forwards $persistance;
        }
      }
    }

    // Iterate through $notification-status-color map and create the proper classes
    @each $status-type, $status-data in $notification-status {   
      &[data-notification-status="#{$status-type}"] {
        background-color: map-get($status-data, color);
        
        @if($notification-show-icon) and map-get($status-data, icon) {
          &:before {
            content: '';
            display: block;
            width: $notification-icon-size;
            height: $notification-icon-size;
            min-width: $notification-icon-size;
            margin-right: $notification-toast-margin;
            background: get-icon($status-type, icon, darken(map-get($status-data, color), 20%));
          }
        }
      }
    }
}


// Other styles related to this specific pen
body { 
  width: 100%;
  height: 100vh;
  background: linear-gradient(to bottom, #be93c5, #7bc6cc);
  font-family: 'Source Sans Pro', sans-serif;
  text-rendering: optimizeLegibility;
}

main {
  width: 100vw; 
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

h1 {
  color: #fff;
  font-size: 55px;
}

p {
  line-height: 1.5
}

nav {
  margin-top: 50px;
}

.button {
  padding: 15px 20px;
  border: 2px solid white;
  border-radius: 5px;
  font-size: 13px;
  font-weight: 700; 
  text-transform: uppercase;
  text-decoration: none;
  color: white;
  
  &:hover,
  &.is-active {
    color: #be93c5;
    background-color: white;
  }
}

// Types of notifications
.top-left { 
  @include c-notification($position: 'top left', $type: toast, $animation: slide, $duration: 1s, $persistance: 5s)
}

.top-right {
  @include c-notification($position: 'top right', $type: toast, $animation: fade, $duration: 1s, $persistance: 3s)
}

.bottom-right {
  @include c-notification($position: 'bottom right', $type: toast, $animation: slide, $duration: 1s, $persistance: 3s)
}

.bottom-left {
  @include c-notification($position: 'bottom left', $type: toast, $animation: fade, $duration: 1s, $persistance: 3s)
}

.bar-top {
  @include c-notification($position: 'top', $type: bar, $animation: slide, $duration: 1s, $persistance: 3s)
}

.bar-bottom {
  @include c-notification($position: 'bottom', $type: bar, $animation: fade, $duration: 1s, $persistance: 3s)
}
              
            
!

JS

              
                $('.button').on('click', function(event){
  var type = $(this).data('type');
  var status = $(this).data('status');
  
  $('.button').removeClass('is-active');
  $(this).addClass('is-active');
  
  $('.notify')
    .removeClass()
    .attr('data-notification-status', status)
    .addClass(type + ' notify')
    .addClass('do-show'); 
  
  event.preventDefault();
})
              
            
!
999px

Console