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

Save Automatically?

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

              
                .wrapper
  .widget
    .location
      input#location-box(type="text" placeholder="Click the Pin to Start...")
      i#geolocate.fa.fa-map-marker
    .current
      .icon
        canvas(id='summary-icon', width='80', height='80')
      .description
    .hourly
    .conversion
      button Convert to Metric
  .attribution
    a(href="https://darksky.net/poweredby/") Powered by Dark Sky
              
            
!

CSS

              
                $dark-gray: #333;
$gradient-color1: #83a4d4;
$gradient-color2: #b6fbff;
$main-font: 'Muli', sans-serif;
$widget-background: #046f96;
$lighter: lighten($widget-background, 5%);
$lightest: lighten($widget-background, 10%);
$darker: darken($widget-background, 5%);
$darkest: darken($widget-background, 10%);
$primary: #fff;

@mixin clear-defaults {
  html,
  body {
    margin: 0;
    overflow: hidden;
    padding: 0;
  }

  h1, h2, h3, h4, h5, h6, p {
    margin: 0;
    padding: 0;
  }
}

@mixin clearfix {
  &::after {
    clear: both;
    content: '';
    display: table;
  }
}

@mixin placeholder-color {
  &::placeholder {
    color: $primary;
    opacity: .75;
  }
}

@include clear-defaults;

.attribution {
  background: $dark-gray;
  bottom: 0;
  padding: 3px;
  position: absolute;
  right: 0;

  a {
    color: $primary;
    font-family: $main-font;
    font-size: 12px;
    text-decoration: none;
  }
}

.conversion {
  background: $widget-background;
  opacity: 0;
  transition: opacity 1s 1.5s;

  button {
    background: $darker;
    border: 0;
    border-radius: 10px;
    color: $primary;
    font: 400 12px $main-font;
    outline: none;
    padding: 3px 10px;

    &:hover {
      cursor: pointer;
    }

    &:focus {
      outline: none;
    }
  }
}

.wrapper {
  align-items: center;
  background: linear-gradient(to left, $gradient-color1, $gradient-color2);
  display: flex;
  height: 100vh;
  justify-content: center;
  position: relative;
  width: 100%;
}

.widget {
  background: $widget-background;
  border-radius: 10px;
  box-shadow: 0 2px 10px $darkest;
  height: 55px;
  max-width: 425px;
  min-width: 290px;
  text-align: center;
  transition: height .65s ease-out;
  width: 90%;

  .location {
    display: flex;
    height: 50px;

    i {
      align-items: center;
      background: lighten($widget-background, 5%);
      border-bottom: 5px solid $lightest;
      border-radius: 0 10px 0 0;
      box-sizing: border-box;
      color: $primary;
      display: flex;
      font-size: 36px;
      height: 50;
      justify-content: center;
      padding: 5px 0;
      width: 15%;

      &:hover {
        background: $darker;
        cursor: pointer;
      }
    }

    input {
      @include placeholder-color;
      background: $lighter;
      border: 0;
      border-bottom: 5px solid $lightest;
      border-radius: 10px 0 0;
      border-right: 2px solid $lightest;
      box-sizing: border-box;
      color: $primary;
      font-family: $main-font;
      font-size: 24px;
      font-weight: 700;
      height: 50px;
      outline: none;
      text-align: center;
      width: 85%;
    }
  }
}

.hourly {
  align-items: center;
  display: flex;
  flex-direction: column;
  font: 700 16px $main-font;
  justify-content: center;
  opacity: 0;
  padding: 0;
  text-align: center;
  transition: opacity 1s 1s;

  .row {
    background: $lighter;
    position: relative;
    width: calc(100% - 2px);

    canvas {
      margin: 0;
      padding: 0;
      position: relative;
      top: 5px;
    }

    &:nth-child(2n) {
      background: $widget-background;
    }
  }

  p {
    color: $primary;
    padding: 17px;
    text-align: left;

    .right {
      @include clearfix;
      float: right;
      padding-top: 8px;
    }

    .pad-time {
      border-right: 1px solid $primary;
      margin-right: 8px;
      padding-right: 4px;
    }
  }
}

.current {
  align-items: center;
  border-bottom: 1px solid $darker;
  display: flex;
  justify-content: center;
  opacity: 0;
  padding: 10px 0;
  text-align: center;
  transition: opacity 2s .5s;
  width: 100%;

  .icon {
    height: 80px;
    padding: 0;
  }

  .description {
    align-items: center;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-left: 15px;

    ul {
      color: $primary;
      font-family: $main-font;
      font-size: 14px;
      height: 15px;
      margin-top: 8px;
      padding: 0;

      li {
        background: $darker;
        border-radius: 5px;
        display: inline;
        margin-right: 5px;
        padding: 5px;
      }
    }

    h1 {
      color: $primary;
      font-family: $main-font;
      font-size: 36px;
      font-weight: 900;
      width: 100%;
    }
  }
}

// fix mobile sizing
@media screen and (max-width: 525px) {
  .widget {
    .location {
      input {
        font-size: 20px;
      }
    }
  }

  .current {
    .description {
      padding-left: 10px;

      h1 {
        font-size: 30px;
      }

      ul {
        font-size: 12px;

        li {
          margin-right: 0;
        }
      }
    }
  }

  .hourly {
    font: 700 14px $main-font;

    p {
      .right {
        padding-top: 11px;
      }
    }
  }
}

@media screen and (max-width: 375px) {
  .attribution {
    padding: 0;

    a {
      font-size: 10px;
    }
  }

  .widget {
    .location {
      input {
        font-size: 16px;
      }
    }
  }

  .current {
    .description {
      padding-left: 10px;

      h1 {
        font-size: 24px;
      }

      ul {
        font-size: 10px;

        li {
          margin-right: 0;
        }
      }
    }
  }

  .hourly {
    font: 700 12px $main-font;

    p {
      .right {
        padding-top: 13px;
      }
    }
  }
}

              
            
!

JS

              
                const locationInput = $('#location-box');
const currentBox = $('.current');
const convertBtn = $('button');
const hourlyBox = $('.hourly');
const conversionBox = $('.conversion');
const descriptionBox = $('.description');
const widget = $('.widget');
const WIDGET_HEIGHT = '560px';
let skycons = new Skycons({'color': 'white'});
let geocodedObj = '';
let hData = {};
let wData = {};

let curUnit = 'imperial';
const units = {
  'imperial' : {
    'temp' : '°F',
    'speed' : 'MPH'
  },
  'metric' : {
    'temp' : '°C',
    'speed' : 'KPH'
  }
};


$(document).ready(() => {
// bind events for geolocation or geocoding
  bindEvents();
});

function loadWeather(location) {
  // if geocoded from google api
  if (typeof location === 'object') {
    geocodedObj = location; // save a copy for later
    location = `${location.results[0].geometry.location.lat},${location.results[0].geometry.location.lng}`;
    locationInput.val(geocodedObj.results[0].formatted_address);
  } else {
    locationInput.val('From Geolocation');
  }

  $.ajax({
    method: 'GET',
    dataType: 'jsonp',
    url: REQ_URL + API_KEY + '/' + location,
    success: parseWeather,
    error: logError
  });

}

function logError(err) {
  console.log(err.statusText);
}

function parseLocationFromValue() {
  // change spaces to + signs for URL
  return locationInput.val().split(' ').join('+');
}

function parseWeather(weather) {

  hData = weather.hourly.data;
  wData = weather;
  // expansion animations
  descriptionBox.css('display: block');
  widget.css('height', WIDGET_HEIGHT);

  // Add all data to temps and hourly
  showData();

  // set the weather summary icon and animate
  animateHourlyIcons();

  // animate opacity after all data is added
  currentBox.css('opacity', '1.0');
  hourlyBox.css('opacity', '1.0');
  conversionBox.css('opacity', '1.0');

}

// DarkSky free-tier API key
// Only shown publicly to use on Codepen without a back-end.
// Get your own free API key at https://darksky.net/dev/
const API_KEY = 'ef7f2ef3ac83b2547e25b6380e022f60';
const REQ_URL = 'https://api.darksky.net/forecast/';

function bindEvents() {
  // Geolocation Button Clicked
  $('#geolocate').click(() => {
    locationInput.attr('placeholder', '');
    locationInput.val('Getting Geolocation...');
    if ('geolocation' in navigator) {
      navigator.geolocation.getCurrentPosition((loc) => {
        loadWeather(`${loc.coords.latitude},${loc.coords.longitude}`);
      });
    } else {
      alert('Your browser does not support geolocation or you have not given this page permission to use your location.');
    }
  });

  // Manually Typed Location

  convertBtn.click(() => {
    curUnit = curUnit === 'imperial' ? 'metric' : 'imperial';
    showData();
    animateHourlyIcons();
    if (curUnit === 'metric') {
      convertBtn.text('Convert to Imperial')
    } else {
      convertBtn.text('Convert to Metric');
    }
  });

}

function showData() {


  descriptionBox.html(`<h1>${wData.currently.summary}</h1>`);

  descriptionBox.append(
    `<ul>
      <li>Now <strong>${convert(wData.currently.temperature)}</strong></li> 
      <li>High <strong>${convert(wData.daily.data[0].temperatureMax)}</strong></li>
      <li>Low <strong>${convert(wData.daily.data[0].temperatureMin)}</strong></li>
     </ul>`);

  hourlyBox.html(
    `<div class="row">
      <p><span class="pad-time">${moment.unix(hData[0].time).format('hA')}</span> <canvas id="hour1" width="25" height="25"></canvas> ${hData[0].summary} 
      ${convert(hData[0].temperature)} <span class="right">WS: ${convert(hData[0].windSpeed, 'speed')}</span></p>
     </div>
     <div class="row">
      <p><span class="pad-time">${moment.unix(hData[1].time).format('hA')}</span> <canvas id="hour2" width="25" height="25"></canvas> ${hData[1].summary} 
      ${convert(hData[1].temperature)} <span class="right">WS: ${convert(hData[1].windSpeed, 'speed')}</span></p>
     </div>
     <div class="row">
      <p><span class="pad-time">${moment.unix(hData[2].time).format('hA')}</span> <canvas id="hour3" width="25" height="25"></canvas> ${hData[2].summary} 
      ${convert(hData[2].temperature)} <span class="right">WS: ${convert(hData[2].windSpeed, 'speed')}</span></p>
     </div>
     <div class="row">
      <p><span class="pad-time">${moment.unix(hData[3].time).format('hA')}</span> <canvas id="hour4" width="25" height="25"></canvas> ${hData[3].summary} 
      ${convert(hData[3].temperature)} <span class="right">WS: ${convert(hData[3].windSpeed, 'speed')}</span></p>
     </div>
     <div class="row">
      <p><span class="pad-time">${moment.unix(hData[4].time).format('hA')}</span> <canvas id="hour5" width="25" height="25"></canvas> ${hData[4].summary} 
      ${convert(hData[4].temperature)} <span class="right">WS: ${convert(hData[4].windSpeed, 'speed')}</span></p>
     </div>
     <div class="row">
      <p><span class="pad-time">${moment.unix(hData[5].time).format('hA')}</span> <canvas id="hour6" width="25" height="25"></canvas> ${hData[5].summary} 
      ${convert(hData[5].temperature)} <span class="right">WS: ${convert(hData[5].windSpeed, 'speed')}</span></p>
     </div>
     `);
}

function convert(val, type = 'temp') {
  // rounds and converts between C and F or MPH and KPH for windspeed
  let converted = 0;
  const KPH_RATIO = 1.609344;
  if(curUnit === 'imperial' && type === 'temp') {
    converted = Math.round(Number(val)) + units[curUnit].temp;
  } else if (curUnit === 'metric' && type === 'temp') {
    converted = Math.round((Number(val) - 32) * (5 / 9)) + units[curUnit].temp;
  } else if (curUnit === 'imperial' && type === 'speed') {
    converted = Math.round(Number(val)) + units[curUnit].speed;
  } else {
    converted = Math.round(Number(val) * KPH_RATIO) + units[curUnit].speed;
  }
  return converted;
}

function animateHourlyIcons() {
  skycons.set('summary-icon', wData.currently.icon);
  skycons.set('hour1', hData[0].icon);
  skycons.set('hour2', hData[1].icon);
  skycons.set('hour3', hData[2].icon);
  skycons.set('hour4', hData[3].icon);
  skycons.set('hour5', hData[4].icon);
  skycons.set('hour6', hData[5].icon);
  skycons.play();
}
              
            
!
999px

Console