Avatar Change Interface

In this example below you will see how to do a Avatar Change Interface with some HTML / CSS and Javascript

This is a pen that allows you to upload a new image and cycle through a list of images. It is a concept for cycling through avatars or user profile images. It features some error handling and some ARIA accessibility support as well.

Thumbnail
This awesome code was written by Joey Lea, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright Joey Lea ©
  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Avatar Change Interface</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div class="container">
  <div class="wrap">
    <h1>Change your avatar</h1>
    <div class="profile">
      <div class="profile__options">
         <label for="upload" onkeydown="handleAriaUpload(event, this)" id="upload_label" title="Upload New File" tabindex="2" class="aria-upload">upload new</label>
        <a class="last-btn btn" tabindex="2" onclick="changeAvatar('last')"
        onkeyup="if(event.keyCode !== 13) return;changeAvatar('last');">
          &larr;
        </a>

        <a class="next-btn btn" tabindex="3" onclick="changeAvatar('next')" onkeyup="if(event.keyCode !== 13) return;changeAvatar('next');">
          &rarr;
        </a>
      </div>
      <div class="avatar" id="avatar">
        <div id="preview"><img src="https://source.unsplash.com/h13Y8vyIXNU/150x150" id="avatar-image" class="avatar_img" id="">
        </div>
        <div class="avatar_upload" >
          <label class="upload_label">Upload
            <input type="file" id="upload">
          </label>
        </div>
      </div>
      <div class="nickname">
        <span id="name" tabindex="4" data-key="1" contenteditable="true" onkeyup="changeAvatarName(event, this.dataset.key, this.textContent)" onblur="changeAvatarName('blur', this.dataset.key, this.textContent)">Walrus</span>
      </div>
    </div>
  </div>
</div>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/ovdojoey/avatar-change-interface-xOxPNg */
body{
  font-family:  'Avenir', serif;
  background: #213;
  margin: 0;
  padding: 0;
}
.container{
  height: 100vh;
  min-height: 350px;
  width: 100vw;
  display: flex;
  align-items:center;
  padding: 0;
  margin: 0;
  flex-wrap: wrap;
}
.wrap{
  width: 100%;
  text-align: center;
}
.wrap h1{
  color: #fff;
}
.profile{
  margin: auto;
  width: 95%;
  max-width: 400px;
  background: #ecf0f2;
  border-radius: 10px;
  padding: 15px 10px 30px 10px;
  position: relative;
/*   border: 1px solid #ccc; */
  box-shadow: 0px 1px 7px rgba(2,2,2,0.2);
}
.profile__options{
  display: flex;
  flex-wrap: nowrap;
  width: 90%;
  margin: auto;
  justify-content: space-between;
  padding-bottom: 10px;
  color: #666;
}
.upload-btn{
  font-size:13px;
  text-transform: uppercase;
  color: #888;
}
#upload_label{
  cursor: pointer;
  position: absolute;
  left: 15px;
  top: 12px;
  font-size: 14px;
}
#upload_label:hover, #upload_label:focus{
  color: #222;
}
.last-btn, .next-btn{
  top: 110px;
  position: relative;
  font-size: 22px;
}
.btn{
  cursor: pointer;
}
.btn:focus,.btn:hover{
  color:rgba(44,105, 1  51, 1);
}
.avatar{
  width: 150px;
  height: 150px;
  border-radius: 100%;
  border: 2px solid #fff;
  margin: 10px auto;
  position: relative;
  overflow: hidden;
  z-index: 2;
  transform: translateZ(0);
  transition: border-color 200ms;
}
.avatar--upload-error{
  border-color: #F73C3C;
  animation: shakeNo 300ms 1 forwards;
}
@keyframes shakeNo{
  20%, 60%{
    transform: translateX(6px);
  }
  40%, 80%{
    transform: translate(-6px);
  }
}
.avatar:hover .avatar_upload, .avatar--hover .avatar_upload{
  opacity: 1;
}
.avatar:hover .upload_label, .avatar--hover .upload_label{
  display: block;
}
#preview::after{
  content: 'Loading...';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  text-align: center;
  z-index: -1;
  line-height: 150px;
  color: #999;
}
.avatar_img--loading{
  opacity: 0;
}
.avatar_img{
  width: 100%;
  height: auto;
  animation: inPop 250ms 150ms 1 forwards cubic-bezier(0.175, 0.885, 0.32, 1.175);
  transform: scale(0);
  opacity: 0;
}
@keyframes inPop {
  100%{
    transform: scale(1);
    opacity: 1;
  }
}
.avatar_img--rotate90{
  transform: rotate(90deg);
}
.avatar_upload{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  text-align: center;
  height: 100%;
  background: #25cfe3;
  background: rgba(44,205, 251, 0.6);
  display: flex;
  align-items: center;
  opacity: 0;
  transition: opacity 500ms;
}
.upload_label{
  color: #111;
  text-transform: uppercase;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
  padding: 4px;
  border-radius: 3px;
  min-width: 60px;
  width: 100%;
  max-width: 80px;
  margin: auto;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
  background: #fff;
  animation: popDown 300ms 1 forwards;
  transform: translateY(-10px);
  opacity: 0;
  display: none;
  transition: background 200ms, color 200ms;
}
@keyframes popDown{
  100%{
    transform: translateY(0);
    opacity: 1;
  }
}
.upload_label:hover{
  color: #fff;
  background: #222;
}
#upload{
  width: 100%;
  opacity: 0;
  height: 0;
  overflow: hidden;
  display: block;
  padding: 0;
  text-align: center;
}
.nickname{
  text-align: center;
  font-weight: 400;
  font-size: 20px;
  color: #666;
  position: relative;
}
#name:hover{
  outline: lightblue auto 5px;
  outline: -webkit-focus-ring-color auto 5px;
  
}

/*Downloaded from https://www.codeseek.co/ovdojoey/avatar-change-interface-xOxPNg */
var upload = document.getElementById("upload");
var preview = document.getElementById("preview");
var avatar = document.getElementById("avatar");
var avatar_name = document.getElementById("name");
var avatar_name_change_box =
document.getElementById("change-name-box");

var avatars = {
  srcList: [
    {
      name: "Cosmos",
      src: encodeURIComponent("https://source.unsplash.com/rTZW4f02zY8/150x150")
    },
    {
      name: "Walrus",
      src: encodeURIComponent("https://source.unsplash.com/h13Y8vyIXNU/150x150")
    },
     {
      name: "Flowers",
      src: encodeURIComponent("https://source.unsplash.com/PwWkzeJeJZE/150x150")
    },
    {
      name: "Dog",
      src: encodeURIComponent("https://source.unsplash.com/oCJuJQqvCzc/150x150")
    }
  ],
  activeKey: 1,
  add: function(_name, _src){
    this.activeKey = this.srcList.length;
    return (this.srcList.push({name: _name, src: encodeURIComponent(_src)}) - 1);
  },
  changeName: function(key, _name) {
    
    if ( !Number.isInteger(key) ) {
      return false;
    }
    this.srcList[key].name = _name;
    if ( avatar_name.dataset.key == key)
    {
      avatar_name.textContent = _name;  
    }
    return _name;
  },
  showNext: function(){
    
    var _next = this.activeKey + 1;
    if ( _next >= this.srcList.length ) {
      _next = 0;
    }
    this.showByKey(_next);
    
  },
  showLast: function(){
    var _next = this.activeKey - 1;
    if ( _next < 0 ) {
      _next = this.srcList.length - 1;
    }
    this.showByKey(_next);
  },
  showByKey: function(_next) {
    var _on = this.srcList[_next];
    if ( !_on.name ) return;
    
    while(preview.firstChild) {
      preview.removeChild(preview.firstChild);
    }
    
    var img = document.createElement("img");
    img.src = decodeURIComponent(_on.src);
    img.className = "avatar_img--loading";
    img.onload = function() {
      img.classList.add("avatar_img");
    }
    avatar_name.textContent = _on.name;
    avatar_name.setAttribute("data-key", _next);
    preview.appendChild(img);
    this.activeKey = _next;
  }
};

function showAvatar(key) {
  if ( !key ) {
    key = avatars.activeKey;
  }
  
}

/*

/** Handle uploading of files */
upload.addEventListener("change", handleFiles, false);
function handleFiles() {
  var files = this.files;
  for (var i = 0; i < files.length; i++) {
    var file = files[i];
    var imageType = /^image\//;
    
    if (!imageType.test(file.type)) {
      avatar.classList.add("avatar--upload-error");
      setTimeout(function(){
        avatar.classList.remove("avatar--upload-error");
      },1200);
      continue;
    }
    
    avatar.classList.remove("avatar--upload-error");
    
    while(preview.firstChild) {
      preview.removeChild(preview.firstChild);
    }
    
    var img = document.createElement("img");
    img.file = file;
    img.src = window.URL.createObjectURL(file);
    img.onload = function() {
      // window.URL.revokeObjectURL(this.src);
    }
    img.className ="avatar_img";
    
    /* Clear focus and any text editing mode */
    document.activeElement.blur();
    window.getSelection().removeAllRanges();
    
    var _avatarKey = avatars.add(file.name, img.src);
    avatar_name.textContent = file.name;
    avatar_name.setAttribute("data-key", _avatarKey);
    preview.appendChild(img);
  }
}

/** Inline functions */
window.changeAvatarName = function(event, key, name) {
  if (event.keyCode != 13 && event != 'blur') return;
  key = parseInt(key);
  if ( !name ) return;
  var change = avatars.changeName(key, name);
  document.activeElement.blur();
  // remove selection abilities
  window.getSelection().removeAllRanges();
    
};

window.changeAvatar = function(dir){
  if ( dir === 'next' ) {
    avatars.showNext();
  }
  else {
    avatars.showLast();
  }
};
window.handleAriaUpload = function(e, obj) {
  if(e.keyCode == 13) {
    obj.click();
  }
};

Comments