var app = angular.module('app', ['thegitfather.flabel']);
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>angular-flabel demo</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="angular-flabel.css" />
    <script data-require="angular.js@1.5.x" src="https://code.angularjs.org/1.5.3/angular.js" data-semver="1.5.3"></script>
    <script src="app.js"></script>
    <script src="angular-flabel.js"></script>
  </head>

  <body>
    <div class="panel panel-primary">
      <div class="panel-heading">
        <h1>angular-flabel demo</h1>
        <code>(v0.0.2)</code>
      </div>
      <div class="panel-body">
        <form class="form-vertical" novalidate>

          <div class="form-group">
            <input id="emailInput" type="email" class="form-control" placeholder="Email address (e.g. peter.smith@example.com)" name="emailInput" required
            ng-model="emailInput"
            flabel="Your Email" />
          </div>

          <div class="form-group huge-label-font-size">
            <input id="inputHugeLabel" type="text" class="form-control" placeholder="Placeholder..." name="inputHugeLabel" required
            ng-model="inputHugeLabel"
            flabel="Label with huge font size" />
          </div>

          <div class="form-group">
            <input id="inputLongLabel" type="text" class="form-control" placeholder="A very long label text" name="inputLongLabel" required
            ng-model="inputLongLabel"
            flabel="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore Duis aute irure dolor in reprehenderit in voluptate velit" />
          </div>

          <div class="form-group">
            <select id="selectFruit" class="form-control" name="selectFruit" required
            ng-model="selectFruit"
            flabel="Your flavor">
              <option value="" disabled>Select your favorite flavor</option>
              <option value="1">Banana</option>
              <option value="2">Chocolate</option>
              <option value="3">Cherry</option>
            </select>
          </div>

          <div class="form-group">
            <textarea class="form-control" placeholder="Enter your message here..." id="textarea"
            ng-model="textareaMessage"
            flabel="Your Message"></textarea>
          </div>

          <div class="form-group huge-label-font-size">
            <input  type="text" class="form-control" name="noLabel" required
            ng-model="noLabel"
            flabel />
          </div>

        </form>
      </div>
    </div>
  </body>

</html>
'use strict';

angular.module('thegitfather.flabel', [])
  .directive('flabel', function() {
    return {
      scope: {},
      require: 'ngModel',
      restrict: 'A',
      link: function(scope, element, attrs, controller) {
        var flabelText = "";
        var $flabelContainer = element.parent();
        var $flabel = angular.element('<label class="flabel"></label>');

        flabelText = getLabelText();

        if (!flabelText) {
          console.info("no label text found for:", element);
          return; // aborting here
        }

        // set 'for' attribute if element has id
        if (attrs.id !== undefined && attrs.id.length) {
          $flabel.attr("for", attrs.id);
        }

        $flabel.text(flabelText);
        $flabelContainer.addClass('flabeled');
        element.parent().prepend($flabel);

        scope.flabelCtrl = controller;
        scope.$watch('flabelCtrl.$modelValue', checkValueLength);
        scope.$watch('flabelCtrl.$viewValue', checkValueLength);

        function toggleFlabel(show) {
          if (show) {
            if (!$flabelContainer.hasClass('flabel-visible')) {
              $flabelContainer.removeClass('flabel-hidden');
              $flabelContainer.addClass('flabel-visible');
            }
          } else {
            $flabelContainer.removeClass('flabel-visible');
            $flabelContainer.addClass('flabel-hidden');
          }
        }

        function getLabelText() {
          if (attrs.flabel.length) {
            return attrs.flabel;
          } else if (attrs.placeholder !== undefined && attrs.placeholder.length) {
            return attrs.placeholder;
          } else {
            return false;
          }
        }

        function checkValueLength(newValue) {
          if (newValue !== undefined && newValue.length > 0) {
            toggleFlabel(true);
          } else {
            toggleFlabel(false);
          }
        }

      }
    };
  });
body {
  padding: 1em;
}

.panel {
  max-width: 480px;
  min-width: 320px;
  margin: 20px auto;
}

form {
  padding: 1em 0.5em;
}

.tiny-label-font-size {
  font-size: 11px;
}

.huge-label-font-size {
  font-size: 28px;
}

label {
  color: #555;
  font-weight: normal;
}

input[type="text"], input[type="email"], input[type="number"], textarea {
  font-family: monospace;
}

.panel-heading {
  position: relative;
}

.panel-heading h1 {
  margin: 0;
  font-size: 16px;
}

.panel-heading code {
  position: absolute;
  top: 0;
  right: 0;
  display: inline-block;
  font-size: 80%;
  color: #fff;
  background-color: #659BC9;
}
.flabeled {
  position: relative;
}

.flabeled label.flabel {
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  padding: 0;
  margin: 0;
  max-height: 0;
  opacity: 0;
  line-height: 1em;
  position: relative;
  z-index: 2;
  transition: all ease 0.2s, opacity ease 0.4s;
}

.flabeled input, .flabeled textarea {
  position: relative;
  z-index: 1;
  transition: all ease 0.1s;
}

.flabel-visible label.flabel {
  margin-bottom: 4px;
  max-height: 100%;
  opacity: 1;
  -webkit-animation: 0.3s bounceInUp;
          animation: 0.3s bounceInUp;
  pointer-events: auto;
}

.flabel-hidden label.flabel {
  opacity: 0;
  pointer-events: none;
}

@-webkit-keyframes bounceInUp {
  from, 60%, 75%, 90%, to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
            animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    -webkit-transform: translate3d(0, 10em, 0);
            transform: translate3d(0, 10em, 0);
  }
  60% {
    -webkit-transform: translate3d(0, -0.6em, 0);
            transform: translate3d(0, -0.6em, 0);
  }
  75% {
    -webkit-transform: translate3d(0, 0.33em, 0);
            transform: translate3d(0, 0.33em, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -0.15em, 0);
            transform: translate3d(0, -0.15em, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
            transform: translate3d(0, 0, 0);
  }
}

@keyframes bounceInUp {
  from, 60%, 75%, 90%, to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
            animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }
  from {
    -webkit-transform: translate3d(0, 10em, 0);
            transform: translate3d(0, 10em, 0);
  }
  60% {
    -webkit-transform: translate3d(0, -0.6em, 0);
            transform: translate3d(0, -0.6em, 0);
  }
  75% {
    -webkit-transform: translate3d(0, 0.33em, 0);
            transform: translate3d(0, 0.33em, 0);
  }
  90% {
    -webkit-transform: translate3d(0, -0.15em, 0);
            transform: translate3d(0, -0.15em, 0);
  }
  to {
    -webkit-transform: translate3d(0, 0, 0);
            transform: translate3d(0, 0, 0);
  }
}