• You are currently browsing the archives for the General category.

  • Archive for the ‘General’ Category

    The Ryanair approach to progressive enhancement

    Sunday, May 24th, 2015

    I fly – a lot. I spend more time in airports, in the air, hotel rooms and conferences than at home. As I am a natural recording and analysing device, I take in a lot of things on my travels. People at airports are stressed, confused, don’t pay attention to things, eat badly and are not always feeling good. They are tired, they feel rushed and they want just to get things over with and get where they want to go. Others – those new to travel – are overly excited about everything and want to things right, making mistakes because they are too eager. Exactly what users on the web are like. I found that companies who use technology for the benefit of their users are those people love and support. That’s what progressive enhancement means to me. But let’s start at the beginning.

    Getting somewhere by plane is pretty simple. You buy a ticket and you get a booking confirmation number, an airport you leave from, a time and a destination airport. To claim all this and get on the flight, you also need to prove that you are you. You can do this in domestic flights with the credit card you booked the flight with, a driving license or your passport. For international travels, the latter is always the safest option.

    The main thing you have to fear about flying is delays that make you miss your plane. Delays can be natural problems, technical failures with the plane or the airport. They could also be issues with air traffic control. It is busy up in the blue yonder, as this gorgeous visualisation shows. Another big issue is getting to the airport in time as all kind of traffic problems can delay you.

    You can’t do much about that – you just have to take it in stride. I plan 3 hours from my house to sitting on the plane.

    Avoid the queue

    One thing you want to avoid is queues. The longer the queue, the more likely you are to miss your plane. Every single person in that queue and their problems become yours.

    Airport QueuePhoto by James Emery

    Airlines understand that and over the years have put improvements in place that make it easier for you to get up in the air.

    In essence, what you need to get in exchange of your information is a boarding pass. It is the proof that all is well and you are good to go.

    Passport with boarding passesPhoto by mroach

    The fool-proof way of doing that is having check-in counters. These have people with computers and you go there, tell them your information and you get your boarding pass. You can also drop off your luggage and you get up-to-date information from them on delays, gates and – if you are lucky – upgrades. Be nice to them – they have a tough job and they can mess up your travels if you give them a tough time.

    Improvement: self check-in counters

    Manned check-in counters are also the most time consuming and expensive way. They also don’t scale to hundreds of customers – hence the queues.

    Self check-in counters

    The first step to improve this was self-check-in terminals. If you allow people to type in their booking confirmation and scan their passport, a machine can issue the boarding pass. You can then have a special check-in counter only for those who need to drop off luggage. Those without luggage, move on to the next level without having to interact with a person behind the counter and take up a space in the queue. Those who don’t know how to use the machine or who forgot some information or encounter a technical failure can still go to a manned check-in counter.

    Improvement: mobile apps

    Mobile boarding pass in app

    Nowadays this is even better. We have online check-in that allows us to check in at home and print out our own boarding passes. As printer ink is expensive and boarding passes tend to be A4 and littered with ads, you can also use apps on smartphones.

    Of course, every airline has their own app and all work different and – at times – in mysterious ways. But let’s not dwell on that.

    Apps are incredible – they show you when your flight happens, delays, and you don’t need to print out anything. You get this uplifting feeling that you’re part of a technical elite and that you know your stuff.

    Mobile app offering an upgrade for 'null'

    Of course, as soon as you go high-tech, things also break:

    • You can always run out of battery
    • Apps crash and need to have a connection to re-start and re-fresh your booking content. That’s why a lot of people take screenshots of their boarding passes in the app.
    • You need to turn off your phone on planes, which means on changing to another plane you need to re-boot it, which takes time.
    • Some airports don’t have digital readers of QR codes or have access to priority lane only as a rubber stamp on a paper boarding pass (looking at you, SFO). That’s why you need a printout.
    • Staff checking your boarding pass at security and gate staff tend to wait for your phone display to go to sleep before trying to scan it. Then they ask you to enter your unlock code. There is probably some reason for that.
    • Some security lanes need you to keep your boarding pass with you but you can’t keep your phone on you as it needs to be X-Rayed. You see the problem…

    Despite all that, you are still safe. When things go wrong, there are the fallbacks of the machines or the manned counter to go back to.

    This is progressive enhancement

    This, is progressive enhancement.

    • You put things in place that work and you make it more convenient for your users who have technical abilities.
    • You analyse the task at hand and offer the most basic solution.
    • With this as a security blanket, you think of ways to improve the experience and distribute the load.

    You make it easier for users who are frequently using your product. That’s why I get access to fast-track security lanes and lounges. I get a reward for saving the company time and money and allowing them to cater to more users.

    You almost never meet people in these lounges who have bad things to say about the airline. Of course they are stressed – everybody at an airport is – but there is a trust in the company they chose and good experiences means having a good relationship. You can check in 24 hours before your flight and all you bring to the airport is your phone and your passport. If you fail to do so, or you feel like it, you can still go to the counter. You feel like James Bond or Tony Stark.

    Forcing your users to upgrade

    Then there is Ryanair and other budget airlines. You will be hard pushed to find anyone who loves them. The mood ranges from “meh, it is convenient, as I can afford it” to “necessary evil” and ends in “spawn of satan and bane of my existence”. Why is that?

    Well, budget airlines try to save and make money wherever they can. They have less ground staff and check-in counters. They have online check-in and expect you to bring a printout of your boarding pass. They have draconic measures when it comes to the size and weight of your luggage. They are less concerned when it comes to your available space on the plane or happy to charge extra for it. Instead of using a service it feels like you have to game it. You need to be on your toes, or you pay extra. You feel like you have to work for what you already paid for and you feel not empowered, but stupid when you forgot to have one thing the company requests you to have – things others don’t bother with.

    They also have apps. And pretty ones at that. When everything goes right, these are cool. Yet, these come with silly limitations. These companies chose to offer apps so they can cut down on ground staff and less check-in counters. They are not an improvement or convenience, but become a necessity.

    The “let’s make you queue anyways” app experience

    The other day I was in Italy flying to Germany with Ryanair. I have no Italian data connection and roaming is expensive. I also had no wireless in the hotel or the convention I was at. Ryanair allows me to check-in online with a browser 24 hours before the flight. I couldn’t. When you use the app is even more draconic: you can only check in two hours before the flight. If you remember, I add a my 3 hour trip cushion to the airport to my travels. Which means I am on the road which in London means I am underground without a connection when I need to check in.

    I grumpily queued up at the hot, packed airport in a massive queue full of screaming kids and drunk tourists. Others were people standing over half-unpacked luggage as their passports were missing. When I arrived at the counter, the clerk told me that as I needed to print out my boarding pass or check in with the app. As I failed to do so, I now need to pay 45 Euro for my boarding pass if he were to print it for me.

    This was almost the price of the ticket. I told him that because of the 2 hour period and me not having connectivity, I couldn’t do that. All I got was “this is our policy”.

    I ground my teeth, and connected my roaming data on my phone, trying to check in with the app. Instead of asking for my name and booking confirmation it asked for all kind of extra information. I guess the reason was that I hadn’t booked the ticket but someone had booked it for me. The necessary information included entering a lot of dates with a confusing date picker. In the end, I was one minute late and the app told me there is no way I can check in without going to a counter. I queued up again, and the clerk told me that I can not pay at his counter. Instead I needed to go to the other side of the airport to the ticketing counter, pay there and bring back a printout that I did pay. Of course, there was another queue. Coming back, I ended up in yet another queue, this time for another flight. I barely made it to my plane.

    Guess what my attitude towards future business with this airline is. Right – they have a bleak future with me.

    Progressive enhancement is for the user and you benefit, too

    And this is when you use progressive enhancement the wrong way. Yes, an app is an improvement over queuing up or printing out. But you shouldn’t add arbitrary rules or punish those who can’t use it. Progressive enhancement is for the benefit of the end user. We also benefit a lot from it. Unlike the physical world of airport we can enhance without extra overhead. We don’t need to hire extra ground staff or put up hardware to read passports. All we need to do is to analyse:

    • What is the basic information the user needs to provide to fulfill a task
    • What is the simplest interface to reach this
    • How can we improve the experience for more advanced users and those on more advanced hardware?

    The latter is the main thing: you don’t rely on any of those. Instead you test if they can be applied and apply them as needed.

    Progressive enhancement is not about adding more work to your product. It is about protecting the main use case of your product and then enhance it with new functionality as it becomes available. Google is a great example of that. Turn off JavaScript and you still get a form to enter information in and you get a search result page with ads on it. This is how you find things and Google makes money. Anything else they added over time makes it more convenient for you but is not needed. It also offers them more opportunities to show you more ads and point at other services.

    Use progressive enhancement as a means to reward your users. Don’t expect them to do things for you just to use your product. If the tools you use means your users have to have a “modern” browser and load a lot of script you share your problems with them. You can only get away with that if you offer them a cheaper version of what others offer but that’s a risky race to take part in. You can win their current business, but never their hearts or support. You become a necessary evil, not something they tell others about.

    </may-tour> – I did it!

    Tuesday, May 19th, 2015

    Sitting in the lovely conference hotel Estherea in Amsterdam, I am ready to go to Schipol to fly back home to London. This marks the end of the massive conference tour in beggining May. I can’t believe it all worked out, although I had to re-book one flight and I stayed for two days at each location.

    Chris pumping up a boat called internet others punch holes in
    (sketch from my Beyond Tellerand keynote by Manuel Ortiz)

    Here’s what happened:

    Now it is time to wash my clothes, send all the emails I stacked up during bad connectivity times and clean out my flat to move to another one. Oh yeah, and two more conferences this month :)

    Start of my very busy May speaking tour and lots of //build videos to watch

    Saturday, May 2nd, 2015

    I am currently in the Heathrow airport lounge on the first leg of my May presenting tour. Here is what lies ahead for me (with various interchanges in other countries in between to get from one to the other):

    • 02-07/05/2015 – Mountain View, California for Spartan Summit (Microsoft Edge now)
    • 09/05/2015 – Tirana, Albania for Oscal (opening keynote)
    • 11/05/2015 – Düsseldorf, Germany for Beyond Tellerand
    • 13-14/05/2015 – Verona, Italy – JSDay (opening keynote)
    • 15/05/2015 – Thessaloniki, Greece – DevIt (opening keynote)
    • 18/05/2015 – Amsterdam, The Netherlands – PhoneGap Day (MC)
    • 27/05/2015 – Copenhagen, Denmark – At The Frontend
    • 29/05/2015 – Prague, Czech Republic – J and Beyond

    All packed and ready to go

    I will very likely be too busy to answer a lot of requests this month, and if you meet me, I might be disheveled and unkempt – I never have more than a day in a hotel. The good news is that I have written 3 of these talks so far.

    To while away the time on planes with my laptop being flat, I just downloaded lots of videos from build to watch (you can do that on each of these pages, just do the save-as), so I am up to speed with that. Here’s my list, in case you want to do the same:

    The new challenges of “open”

    Tuesday, April 28th, 2015

    These are my notes for my upcoming keynote at he Oscal conference in Tirana, Albania.

    Today I want to talk about the new challenges of “open”. Open source, Creative Commons, and many other ideas of the past have become pretty much mainstream these days. It is cool to be open, it makes sense for a lot of companies to go that way. The issue is, that – as with anything fashionable and exciting – people are wont to jump on the bandwagon without playing the right tune. And this is one of the big challenges we’re facing.

    Before we go into that, though, let’s recap the effects of going into the open with our work has.

    Creating in the open is an empowering and frightening experience. The benefits are pretty obvious:

    • You share the load – people can help you with feedback, doing research for you, translating your work, building adapters to other environments for you.
    • You have a good chance your work will go on without you – as you shared, others can build upon your work when you moved on to other challenges; or got run over by a bus.
    • Sharing feels good – it’s a sort of altruism that doesn’t cost you any money and you see the immediate effect.
    • You become a part of something bigger – people will use your work in ways you probably never intended, and never thought of. Seeing this is incredibly exciting.

    The downsides of working in the open are based on feedback and human interaction.

    • You’re under constant surveillance – you can’t hide things away when you openly share your work in progress. This can be a benefit as it means your product is higher quality when you’re under constant scrutiny. It can, however, also be stifling as you’re more worried about what people think about your work rather than what the work results in.
    • You have to allocate your time really well – feedback will come 24/7 and in many cases not in a format that is pleasing or – in some cases – even intelligible.
    • You have to pick your battles – people will come with all kind of requests and it is easy to get lost in pleasing the audience instead of finishing your product.
    • You have to prepare yourself for having to adhere to existing procedures – years of open source work resulted in many best practices and very outspoken people are quick to demand you adhere to them or stay off the lawn.

    Hey cool kids, we’re doing the open thing!

    One of the main issues with open is that people are not really aware of the amount of work it is. It is very fashionable to release products as open source. But, in many cases, this means putting the code on GitHub and hoping for a magical audience to help you and fix your problems. This is not how open source prospers.

    Open Source and related ways of working does not mean you give out your work for free and leave it at that. It means that you make it available, that you nurture it and that you are open to giving up control for the benefit of the wisdom of the crowd. It is a two-way, three-way, many way exchange of data and information. You give something out, but you also get a lot back, and either deserves the same attention and respect.

    More and more I find companies and individuals seeing open sourcing not as a way of working, but as an advertising and hiring exercise. Products get released openly but there is no infrastructure or people in place to deal with the overhead this means. It has become a ribbon to attach to your product – “also available on GitHub”.

    We’ve been through that before – the mashup web and open APIs promised us developers that we can build great, scaling and wonderful products by using the power of the web. We pick and mix our content providers with open APIs and build our interfaces on top of that data. This died really quickly and today most APIs we played with are either shut down or became pay-to-play.

    Other companies see “open” as a means to keep things alive that are not supported any longer. It’s like the mythical farm the family dog goes to when the kids ask where you take him when he gets old and sick. “Don’t worry, the product doesn’t mesh with the core business of our company any longer, but it will live on as it is now open source” is the message. And it is pretty much a useless one. We need products that are supported, maintaned and used. Simply giving stuff out for free doesn’t mean this will happen to that product, as it means a lot of work for the maintainers. In many cases shutting a product down is the more honest thing to do.

    If you want to be open about it – do it our way

    The other issue with open is that – ironically – open communities can come across as uninviting and aggressive. We are a passionate bunch, and care a lot about what we do. That can make us appear overly defensive and aggressive. Many long-standing open communities have methodologies in place to ensure quality that on first look can be daunting and off-putting.

    Many companies understand the value of open, but are hesitant to open up their products because of this. The open community can come across as very demanding. And it is very easy to get an avalanche of bad feedback when you release something into the open but you fail to tick all the boxes. This is poison to anyone in a large company trying to release something closed into the open. You have to justify your work to the business people in the company. And if all you have to show is an avalanche of bad feedback and passive-aggressive “oh look, evilcorp is trying to play nice” comments, they are not going to be pleased with you.

    We’re not competing with technology – we’re competing with marketing and tech propaganda

    The biggest issue I see with open is that it has become a tool. Many of the closed environments that are in essence a replacement for the open web are powered by open technologies. This is what they are great for. The plumbing of the web runs on open. We’re a useful cog, and – to be fair – a lot of closed companies also support and give back to these products.

    On the other hand, when you talk about a fully open product and try to bring it to end users, you are facing an uphill battle. Almost every open alternative to closed (or partly open systems) struggles or – if we are honest with ourselves – failed. Firefox OS is not taking the world by storm and brings connectivity to people who badly need it. The Ubuntu phone as an alternative didn’t cause a massive stir. Ello and Diaspora didn’t make a dent in the Facebooks and Twitters of this world. The Ouya game console ran into debt very quickly and now is looking to be bought out.

    The reason is that we’re fooling ourselves when it comes to the current market and how it uses technology.

    Longevity is dead

    We love technology. We love the web. We love how it made us who we are and we celebrate the fights we fought to keep it open. We fight for freedom of choice, we fight for data retention and ownership of data and we worry where our data goes, if it will be available in the future or what happens with it.

    But we are not our audience. Our audience are the digital natives. The people who see a computer, a smartphone and the internet as a given. The people who don’t even know what it means to be offline, and who watch streaming TV shows in bulk without a sense of dread at how much this costs or if it will work. If it stops working, who cares? Let’s do something else. If our phones or computers are broken, well let’s replace them. Or go to the shop and get them repaired for us. If the phone is too slow for the next version of its operating system, fine. Obviously we need to buy a better one.

    The internet and technology has become a commodity, like running water and electricity. Of course, this is not the case all over the world, and in many cases also not when you’re traveling outside the country of your contracts. But, to those who never experienced this, it is nothing to worry about. Bit by bit, the web has become the new TV. Something people consume without knowing how it works or really taking part in it.

    In England, where I live, it is almost impossible to get an internet connection without some digital TV deal as part of the package. The internet access is the thing we use to consume content provided to us by the same people who sold us CDs, DVDs, and BluRays. And those who consume over the internet also fill it up with content taken from this source material. Real creativity on the web, writing and publishing is on the way out. When something is always available, you stop caring for it. It is simply a given.

    Closed by design, consumable by nature

    This really scares me. It means that the people who always fought the open web and the free nature of software have won. Not by better solutions or by more choice. But by offering convenience. We’ve allowed companies with better marketing than us to take over and tell people that by staying in their world, everything is easy and works magically. People trade freedom of choice and ownership of their information for convenience. And that is hard to beat. When everything works, why put effort in?

    The dawn of this was the format of the app. It was a genius idea to make software a consumable, perishable product. We moved away from desktop apps to web based apps a long time ago. Email, Calendaring, even document handling has gone that way and Google showed how that can be done.

    With the smartphone revolution and the lack of support for open technologies in the leading platform the app was re-born: a bespoke piece of software written for a single platform in a closed format that needs OS-specific skills and tools to create. For end users, it is an icon. It works well, it looks amazing and it ties in perfectly with the OS. Which is no surprise, as it is written exclusively for it.

    Consumable, perishable products are easier to sell. That’s why the market latched on to this quickly and defined it as the new, modern way to create software.

    Even worse, instead of pointing out the lack of support for interoperable and standardised technology in the operating systems of smart devices, the tech press blamed said technologies for not working on them as well as the native counterparts do.

    Develop where the people are

    This constant re-inforcement of closed as a good business and open as not ready and hard to do has become a thing in the development world. Most products these days are not created for the web, independent of OS or platform. The first port of call is iOS, and once its been a success there, maybe Android. But only after complaining that the fragmentation is making it impossible to work. Fragmentation that has always been a given in the open world.

    A fool’s errand

    It seems open has lost. It has, to a degree. But there are already signs that what’s happening is not going to last. People are getting tired of apps and being constantly reminded by them to do things for them. People are getting bored of putting content in a system that doesn’t keep them excited and jump from product to product almost monthly. The big move of almost every platform towards light-weight messaging systems instead of life streams shows that there is a desperate attempt to keep people interested.

    The big market people aim for is teenagers. They have a lot of time, they create a lot of interactions and they have their parent’s money to spend if they nag long enough.

    The fallacy here is that many companies think that the teenagers of now will be the users of their products in the future. When I remember what I was like as a teenager, there is a small chance that this will happen.

    We’re in a bubble and it is pretty much ready to burst. When the dust settles and people start wondering how anyone could be foolish enough to spend billions on dollars on companies that promise profits and pivot every few months when it didn’t come we’ll still be there. Much like we were during the first dotcom boom.

    We’re here to help!

    And this is what I want to close with. It looks dire for the open web and for open technologies right now. Yes, a lot is happening, but a lot is lip-service and many of the “open solutions” are trojan horses trying to lock people into a certain service infrastructure.

    And this is where I need you. The open source and open in general enthusiasts. Our job now is to show that what we do works. That what we do matters. And that what we do will not only deliver now, but also in the future.

    We do this by being open. By helping people to move from closed to open. Let’s be a guiding mentor, let’s push gently instead of getting up in arms when something is not 100% open. Let’s show that open means that you build for the users and the creators of now and of tomorrow – regardless of what is fashionable or shiny.

    We have to move with the evolution of computing much like anybody else. And we do it by merging with the closed, not by trying to replace it. This failed and will also in the future. We’re not here to create consumables. We’re here to make sure they are made from great, sustainable and healthy parts.

    Keeping it simple: coding a carousel

    Wednesday, April 8th, 2015

    One of the things that drives me crazy in our “modern development” world is our fetish of over-complicating things. We build solutions, and then we add layers and layers of complexity for the sake of “making them easier to maintain”. In many cases, this is a fool’s errand as the layers of complexity and with them the necessary documentation make people not use our solutions. Instead, in many cases, people build their own, simpler, versions of the same thing and call it superior. Until this solution gets disputed and the whole dance happens once again.

    In this article I want to approach the creation of a carousel differently: by keeping it as simple as possible whilst not breaking backwards compatibility or have any dependencies. Things break on the web. JavaScript might not be loaded, CSS capabilities vary from browser to browser. It is not up to us to tell the visitor what browser to use. And as good developers we shouldn’t create interfaces that look interactive but do nothing when you click them.

    So, let’s have a go at building a very simple carousel that works across browsers without going overboard. You can see the result and get the code on GitHub.

    The HTML structure of a carousel

    Let’s start very simple: a carousel in essence is an ordered list in HTML. Thus, the basic HTML is something like this:

    <div class="carouselbox">
      <ol class="content">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ol>
    </div>

    Using this, and a bit of CSS we have something that works and looks good. This is the base we are starting from.

    The basic CSS

    The CSS used here is simple, but hints at some of the functionality we rely on later:

    .carouselbox {
      font-family: helvetica,sans-serif;
      font-size: 14px;
      width: 100px;
      position: relative;
      margin: 1em;
      border: 1px solid #ccc;
      box-shadow: 2px 2px 10px #ccc;
      overflow: hidden;
    }
    .content {
      margin: 0;
      padding: 0;
    }
    .content li {
      font-size: 100px;
      margin: 0;
      padding: 0;
      width: 100%;
      list-style: none;
      text-align: center;
    }

    The main thing here is to position the carousel box relatively, allowing us to position the list items absolutely inside it. This is how we’ll achieve the effect. The hidden overflow ensures that later on only the current item of the carousel will be shown. As there is no height set on the carousel and the items aren’t positioned yet, we now see all the items.

    All carousel items visible

    The carousel visuals in CSS

    A lot of carousel scripts you can find will loop through all the items, or expect classes on each of them. They then hide all and show the current one on every interaction. This seems overkill, if you think about it. All we need is two classes:

    • We need a class on the container element that triggers the functional display of our carousel. This one gets applied with JavaScript as this means the look and feel only changes when the browser is capable of showing the effect.
    • We need a class on the currently visible carousel element. This is the odd one out. All the others don’t need any classes.

    We can hard-code these for now:

    <div class="carouselbox active">
      <ol class="content">
        <li>1</li>
        <li class="current">2</li>
        <li>3</li>
        <li>4</li>
      </ol>
    </div>

    All we need to show and hide the different carousel items is to change the height of the carousel container and position all but the current one outside this height:

    .active {
      height: 130px;
    }
    .active li {
      position: absolute;
      top: 200px;
    }
    .active li.current {
      top: 30px;
    }

    You can see this in action here. Use your browser developer tools to move the “current” class from item to item to show a different one.

    carousel changing items

    Interaction with JavaScript

    To make the carousel work, we need controls. And we also need some JavaScript. Whenever you need a control that triggers functionality that only works when JavaScript is executed, a button is the thing to use. These magical things were meant for exactly this use case and they are keyboard, mouse, touch and pen accessible. Everybody wins.

    In this case, I added the following controls in our HTML:

    <div class="carouselbox">
      <div class="buttons">
        <button class="prev"><span class="offscreen">Previous</span>
        </button>
        <button class="next">
          <span class="offscreen">Next</span></button>
      </div>
      <ol class="content">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ol>
    </div>

    Now, here is where the hard-liners of semantic markup could chime in and chide me for writing HTML that is dependent on JavaScript instead of creating the HTML using JavaScript. And they’d be correct to do so. There is nothing that stops me from wrapping this chunk of HTML in a DOM call or innerHTML write-out. However, as buttons are meant to trigger JS functionality, I think it is easier to just keep that in the HTML and allow us thus to style them with much less hassle. As a security precaution, we hide them in the non-active state and show them when the “active” class has been applied:

    .active .buttons {
      padding: 5px 0;
      background: #eee;
      text-align: center;
      z-index: 10;
      position: relative;
    }
    .carouselbox button {
      border: none;
      display: none;
    }
    .active button {
      display: block;
    } 
    .offscreen {
      position: absolute;
      left: -2000px;
    }

    The offscreen parts are there to explain what these buttons really mean as the triangle is not enough for some people.

    All that is left to make the carousel work is the JavaScript. And here it is:

    carousel = (function(){
      var box = document.querySelector('.carouselbox');
      var next = box.querySelector('.next');
      var prev = box.querySelector('.prev');
      var items = box.querySelectorAll('.content li');
      var counter = 0;
      var amount = items.length;
      var current = items[0];
      box.classList.add('active');
      function navigate(direction) {
        current.classList.remove('current');
        counter = counter + direction;
        if (direction === -1 && 
            counter < 0) { 
          counter = amount - 1; 
        }
        if (direction === 1 && 
            !items[counter]) { 
          counter = 0;
        }
        current = items[counter];
        current.classList.add('current');
      }
      next.addEventListener('click', function(ev) {
        navigate(1);
      });
      prev.addEventListener('click', function(ev) {
        navigate(-1);
      });
      navigate(0);
    })();

    As you can see, by relying on CSS and its built-in crawling of the DOM, there is no need for any loop whatsover. Here’s what’s going on in this script:

    • We grab all the HTML elements we need with querySelector.
    • We set the counter to 0 – this is the variable that keeps track of which item of the carousel is currently shown
    • We read the amount of items in the carousel and store them in a variable – this allows us to loop the carousel
    • We set the current item as the first one in the carousel. The current variable will contain a reference to the element currently visible. All we do when the carousel state changes is remove the CSS class from it and shift it to the other one
    • We add the class of “active” to the container element to change its styling and trigger the CSS functionality explained earlier.
    • The navigate method takes a parameter called direction which defines if we should go backwards (negative values) or forwards in the carousel. It starts by removing the “current” class from the current carousel item, thus hiding it. We then modify the counter and make sure it doesn’t go beyond the amount of items available or below 0. In each case we move to the other extreme, thus making the carousel an endless rotating one. We define the new current item and add the class to show it.
    • We apply event handlers to the buttons to navigate forwards and backwards
    • We show the first carousel item by calling navigate with 0 as the value.

    Pretty simple, isn’t it? By allowing CSS to do what it is good at, our JavaScript more or less is only about keeping state and shifting classes around.

    You can see the basic carousel in action here. It’s nothing fancy, but it does the job.

    simple carousel in action

    Getting fancy

    The showing and hiding of the items by positioning them in a container with overflow hidden should work in any browser in use these days – even the ones who should be retired. And as all we do is add and remove CSS classes, we can now tap into the beautiful features browsers have these days. Using transition, opacity and transformation, we can add a pretty effect with a few lines of CSS:

    fancier carousel

    .active li {
      position: absolute;
      top: 130px;
     
      opacity: 0;
      transform: scale(0);
      transition: 1s;
    }
    .active li.current {
      top: 30px;
     
      opacity: 1;
      transform: scale(1);
      transition: 1s;
    }

    The beauty of this is that the performance handling, the timing (in case you click too fast) is handled by the browser for us. No need to count FPS or juggle timeouts. As CSS is a one-off state, this also means that browsers that do not support these features simply don’t show them instead of throwing an error.

    Bullet-proofing our JavaScript

    When a browser in use doesn’t support some JavaScript feature we use, things get trickier. We get an error and things break. Thus, it makes sense to test for the things we use and move on only when there is support for them. In this code, we rely on classList and querySelector, so let’s just check for this:

    if (!document.querySelector || 
      !('classList' in document.body)) {
    return false;
    }

    We could get much more paranoid and ensure that all the DOM elements are available before proceeding but this is overkill. If a maintainer forgets to add the “carouselbox” class to the main element, the error thrown is pretty obvious.

    Bonus round: Stacking with CSS

    One last trick to mention is that if you were to stack all the elements of the carousel visually and only use opacity to blend them then there is a problem with links. You’d always get the link of the first item, no matter which one is shown.

    The trick to work around that is user “pointer-events: none” in your CSS:

    .active li {
      position: absolute;
      top: 130px;
     
      pointer-events: none;
      opacity: 0;
      transform: scale(0);
      transition: 1s;
    }
    .active li.current {
      top: 30px;
     
      pointer-events: auto;
      opacity: 1;
      transform: scale(1);
      transition: 1s;
    }

    You can see this workaround in action here.

    Where to go now?

    The natural drive as a developer now is to enhance this to allow users to define a different starting element to show, to define lots of preset effects that can be chosen with the data attribute, to allow for non-looping carousels and to define an API to allow other components on the page to interact with the carousel. And an API to create and remove and shuffle items of the carousel. And, and and… All of these are great exercises, but let’s ask ourselves: who do we do that for?

    We have such amazing functionality built into the platform of the web now. Maybe it is time to stop writing the perfect generic re-usable widget and just stick with simple things and let people extend them when they need to? Who knows, by not doing the work for them, people might learn to be better coders themselves.