Author: admin

  • Alf’s Cycles-revisited

    Shibi Biju George · MA Web Design + Content Planning · May 2026

    When I look back at the first version of the Alf’s Cycles website I handed in last semester, I feel slightly embarrassed, but also glad that I can now clearly see what was wrong with it. At the time, I thought the site looked modern and polished. The dark theme felt sleek, the images worked visually, and technically the pages functioned. But I was mainly looking at it from my perspective as the designer, not from the perspective of someone actually trying to use it.

    Someone standing outside in Hatfield trying to quickly check if the bike shop was open should not have to scroll all the way to the footer just to find the phone number. That feels obvious to me now, but it honestly was not something I had properly considered during the first version.

    This redesign came from taking that feedback seriously and rebuilding the site around what the user actually needs rather than what simply looks impressive on screen.

    Part One: What the Original Got Wrong

    The HTML structure lacked meaning

    One of the biggest problems with the original site was how I used HTML elements. I treated many elements simply as layout containers rather than thinking about their semantic purpose. The element I misused most was section. I used it almost everywhere without considering whether the content actually represented a distinct section of the page.

    A section element should represent a meaningful block of content with its own heading. Screen readers rely on this structure to understand the page properly. On the homepage, I had an article nested inside multiple unnecessary sections that added no meaning at all.

    There were several smaller semantic issues as well. The footer navigation links were not grouped inside a proper list, which reduced accessibility. I used figcaption outside of a figure element, and I misused the mark element simply as a visual label. None of these mistakes were catastrophic on their own, but together they created a site where the code did not properly reflect the content.

    SEO and page structure problems

    All four pages originally used the exact same title tag. That is a significant SEO issue because search engines rely heavily on titles to understand what each page contains. Using identical titles meant the pages competed against each other rather than supporting each other.

    There were also no meta descriptions, no geolocation metadata, and inconsistent heading structures. Some pages did not even contain a proper h1 heading.

    The contact form was inaccessible

    The contact form relied entirely on placeholder text instead of proper labels. This is a common accessibility mistake because placeholder text disappears once the user starts typing.

    The redesign fixes this by properly associating every form field with a label element using matching for and id attributes.

    The original site also lacked a skip-to-content link, forcing keyboard users to tab through every navigation item before reaching the main content.

    Responsive design was treated as an afterthought

    The original CSS used desktop-first max-width media queries throughout. I was designing for large screens first and then trying to patch problems as the screen became smaller.

    The redesign uses a mobile-first approach with min-width media queries instead. Starting from the smallest screen size and progressively enhancing the layout created a much more reliable responsive structure.

    The dark theme felt too heavy

    The original all-dark design made the site feel closed in and disconnected from cycling as an outdoor activity. Looking back, it felt more like a technology startup than a local bike shop.

    The redesign still uses dark sections, but more intentionally. Dark backgrounds are now balanced with warm off-white areas to create contrast and rhythm instead of overwhelming the entire site.

    Part Two: What Changed

    The HTML now reflects the content properly

    The redesign began with a simple question for every part of the page: what is this content actually supposed to be?

    • section is only used when content has a meaningful heading.
    • article is used for self-contained service cards.
    • address wraps the shop contact details.
    • dl is used for the homepage statistics because they are definition pairs.

    I also removed unnecessary wrapper divs wherever possible. The CSS now relies more on structural selectors and page-based targeting rather than excessive class names.

    PHP includes simplified maintenance

    Shared elements like the header, footer, and head content are now loaded using PHP includes. This means updating navigation or shared content only requires editing one file instead of every individual page.

    The hero section was redesigned around usability

    The homepage hero now fills the full viewport height with a large cycling image and a dark gradient overlay that keeps the heading readable without hiding the image itself.

    The heading uses Instrument Serif, with the second line displayed in italic lime green to match the brand colour used throughout the site.

    Immediately below the hero is a strip containing the shop address, clickable phone number, and opening hours.

    Alternating sections create visual rhythm

    The two sections immediately below the hero were also redesigned carefully to create a stronger visual flow throughout the homepage.

    The Your Local Bike Experts section uses a dark background with a white Instrument Serif heading and a lime left-border accent. A full-bleed workshop image fills the right side of the layout at exactly the same height as the text content.

    Below that, the Bikes, Repairs and Accessories section switches to a light background, with the image placed on the left and the text on the right. This alternating dark and light rhythm helps the page feel more balanced and visually engaging without relying on unnecessary decoration.

    Both sections use CSS Flexbox with align-self: stretch, ensuring the image and text columns always remain equal in height regardless of screen size.

    Typography choices improved readability

    The site uses Instrument Serif for all headings and Inter for all body text, navigation, and labels. Instrument Serif gave the site a more editorial and confident personality, especially when paired with its italic variants used in the lime accent text within the hero section.

    Inter was chosen because it remains extremely clean and readable across different screen sizes and devices. Together, the two typefaces create a balance between personality and usability.

    Accessibility became part of the structure

    Accessibility was considered from the beginning rather than added afterwards. Every page now starts with a skip-to-content link, all form inputs have associated labels, and decorative icons are hidden from screen readers using appropriate ARIA attributes.

    JavaScript does one practical job

    The JavaScript only handles the opening hours feature. It reads the current time from the browser, highlights the current day in the footer, and updates a live status badge showing whether the shop is currently open or closed.

    Performance improvements

    Images are now optimised properly using preload hints, lazy loading, async decoding, and explicit width and height attributes.

    The CSS became much cleaner

    The stylesheet is now organised logically into resets, custom properties, base styles, shared components, page-specific styles, and finally media queries.

    Looking at Both Versions

    The original site had ambition, but the foundations were weak. I focused too heavily on appearance without fully thinking about usability, accessibility, and semantic structure.

    The redesign is much more grounded in what a real visitor actually needs from the site. It is not only visually stronger, but also more accessible, easier to maintain, and far more reliable across devices.

    Declaration of AI Tools Used

    In the interest of academic transparency, this project involved limited use of AI tools during both the writing and development process.The overall design direction, HTML/CSS/PHP implementation, accessibility improvements, responsive layout decisions, testing, and final evaluation of the Alf’s Cycles redesign were completed independently by me.

    ChatGPT (OpenAI)

    Used mainly for proofreading, refining sentence structure, and improving clarity within written reflective content.

    Claude AI (Anthropic)

    Used during the drafting process to help organise ideas and improve the flow of longer reflective sections.

    The final website, including all design decisions, accessibility implementation, coding work, and reflective analysis, represents my own original work.

    Shibi Biju George
    MA Web Design + Content Planning
    May 2026

  • View Transitions: The Future of Web Animation is Here

    How a new browser feature is making smooth animations accessible to everyone


    If you’ve ever visited a modern website and noticed how smoothly photos expand when you click on them, or how elegantly content slides into view, you’ve experienced the magic of web animations. Until recently, creating these polished effects required complicated code and specialist knowledge. But that’s all changing with the View Transition API.

    What Are View Transitions?

    Imagine you’re browsing a photo gallery on a website. You see a grid of small thumbnails and click on one. Instead of the page suddenly jumping to show a larger version, the photo smoothly grows from its small size to fill the screen. That smooth, fluid movement is a view transition.

    In technical terms, the View Transition API provides a mechanism for easily creating animated transitions between different website views. But really, it’s about making websites feel more natural and polished—like watching a film rather than flipping through still photographs.

    How It Actually Works

    The browser does the heavy lifting through a four-step process:

    Step 1: Capture
    When someone triggers an action—clicking a button, navigating, or filtering a list—the browser takes a snapshot of the current view. Think of it as taking a photograph of the webpage, recording where every element sits on the page.

    Step 2: Update the DOM
    Your JavaScript code runs and updates the webpage. Content changes, elements are added or removed, and the layout shifts. All of this happens in a single atomic update.

    Step 3: Snapshot Again
    The browser captures the new view state. Now it has two snapshots: before and after. It can calculate exactly how much things have moved, grown, or shrunk.

    Step 4: Animate
    Here’s where the magic happens. The browser creates smooth CSS animations that morph between the old and new states. Elements appear to move, scale, and fade—all at 60 frames per second using your computer’s graphics processor. Then it tidies up the temporary elements it created.

    The brilliant part? All of this happens automatically. You don’t have to write complex animation code.

    Two Types for Different Needs

    View Transitions come in two flavours, depending on how your website is built:

    Same-Document Transitions (SPAs)
    These work within a single page using the document.startViewTransition() function. They’re perfect for filtering lists, switching tabs, expanding sections, or any content changes that happen without loading a new page.

    https://mdn.github.io/dom-examples/view-transitions/spa

    Cross-Document Transitions (MPAs)
    These work automatically when you navigate between different pages. Both pages just need to opt in with a simple CSS rule, and the browser handles everything else.

    https://mdn.github.io/dom-examples/view-transitions/mpa

    The Code Comparison That Says It All

    Before View Transitions, creating smooth animations looked like this:

    async function updateList(filter) {
      // Animate out old content
      await animateOut();
      
      // Update DOM
      filteredItems = items.filter(item => item.type === filter);
      renderList(filteredItems);
      
      // Animate in new content
      await animateIn();
      
      // Handle focus, accessibility, event listeners...
    }
    

    Dozens of lines of complex code, managing states, coordinating timing, handling edge cases.

    With View Transitions, it’s this simple:

    function updateList(filter) {
      document.startViewTransition(() => {
        filteredItems = items.filter(item => item.type === filter);
        renderList(filteredItems);
      });
    }
    

    Three lines. That’s the entire difference. The browser handles all the animation logic.

    Why This Matters

    1. Less Code to Write
    You’re writing 3 lines instead of 50. This isn’t just about saving time—it’s about being able to focus on your website’s actual functionality instead of wrestling with animation complexity.

    2. Websites Feel Better
    Before View Transitions, many websites had no animations because it was too complicated. Now anyone can add smooth animations. This means regular websites—not just those built by large companies—will feel polished and professional.

    3. Works Everywhere
    Previously, React websites used one animation tool, Vue websites used another, and vanilla JavaScript did something different. Now everyone can use View Transitions. It’s one standard tool that works across the entire web ecosystem.

    4. Web Apps Feel Like Phone Apps
    This might be the most exciting change. Web applications have traditionally felt different from native phone apps—less smooth and less polished. With View Transitions, web apps can be just as fluid as native applications. Users won’t feel the difference any more.

    Can You Use Them Now?

    The short answer: yes, but with some caveats.

    Over 90% of modern browsers support View Transitions:

    • Chrome: 65%+ support
    • Firefox: 25%+ support (recently added)
    • Safari: 10%+ support (iOS 18+)
    • Edge: Included in Chrome statistics
    • Samsung Browser: 60%+ support

    However, the reality is nuanced. At present, support is primarily concentrated in Chrome version 111 and beyond. Whilst the technology is available, not everyone has upgraded to these newer browser versions yet.

    The good news? View Transitions are a progressive enhancement. If someone uses an older browser, your website still works perfectly—they just won’t see the smooth animations. The functionality remains intact.

    Limitations: They’re Not For Everything

    View Transitions are powerful for specific use cases, but they’re not a universal solution.

    What They’re Great For

    • Filtering or sorting a list — Update results and smoothly transition to the new layout
    • Tab switching — Move between sections of a page with animation
    • Expanding sections — Accordion-style content reveals
    • Gallery navigation — Photo galleries, carousels
    • Dashboard view changes — Switching between different data visualizations
    • Page-to-page navigation — Links to different pages with smooth transitions

    If you’re changing what’s displayed on the page and want a smooth visual journey, View Transitions shine.

    What They’re Not For

    Real-time or streaming data: View Transitions need a clear “before” and “after” state. If your data is constantly updating or streaming in, this API doesn’t fit.

    Complex 3D animations: If you need serious 3D effects, WebGL is the tool. View Transitions are about 2D spatial transitions.

    Huge DOM changes: If you’re replacing 80% of the page at once, you might see performance issues. View Transitions work best when there’s a reasonable amount of change.

    Cases where you don’t control the update: Like if data comes from an external source and you don’t have control over how it changes, transitions might not make sense.

    The limitation is really about scope. View Transitions are for discrete state changes. They’re not for continuous animation or streaming. If you have a clear before-and-after state, and you control when the transition happens, you’re in good shape.


    Best Practices: Using View Transitions Wisely

    1. Always Check If It Exists

    javascript

    if (document.startViewTransition) {
      document.startViewTransition(() => {
        updateContent();
      });
    } else {
      updateContent();
    }

    Don’t assume the API is available. Older browsers and some less common browsers won’t have it. Check first, always.

    2. Make Sure Your Fallback Works

    Test your site without View Transitions. Disable the API in DevTools if you have to. Make sure the functionality still works perfectly in browsers that don’t support it. The transition is a bonus, not a requirement.

    3. Don’t Do Heavy Work Inside the Transition

    The callback to startViewTransition() is synchronous. Don’t do expensive calculations or DOM manipulation inside it. Fetch your data first, then call the transition with the update.

    4. Respect When People Don’t Want Motion

    Some users have accessibility needs around motion. Respect the prefers-reduced-motion media query:

    javascript

    const prefersReducedMotion = window.matchMedia(
      '(prefers-reduced-motion: reduce)'
    ).matches;
    
    if (prefersReducedMotion) {
      updateContent(); // Just update, no transition
    } else if (document.startViewTransition) {
      document.startViewTransition(() => updateContent());
    }

    This is both accessible and respectful.

    5. Name Your Transitions Meaningfully

    If you’re giving elements transition names:

    css

    .hero { view-transition-name: hero-section; }
    .sidebar { view-transition-name: sidebar; }

    Use names that describe what’s being transitioned, not how. hero-section is better than slide-left-section.

    6. Test in Multiple Browsers

    Seriously test this. Use Chrome, Firefox, Safari if you can. Make sure unsupported browsers don’t break. Make sure the fallback experience is solid.

    7. Document Why You’re Using Transitions

    If you’re using View Transitions, add a comment explaining why. Future you will appreciate it:

    javascript

    // Use view transition to smoothly show the selected product
    // This creates visual continuity as the user selects from the grid
    function selectProduct(productId) {
      if (document.startViewTransition) {
        document.startViewTransition(() => {
          displayProduct(productId);
        });
      } else {
        displayProduct(productId);
      }
    }

    Getting Started: A Working Example

    Here’s a practical example you can actually use. It’s a photo gallery with View Transitions:

    html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Photo Gallery with View Transitions</title>
      <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: system-ui; padding: 20px; }
        
        .gallery-grid {
          display: grid;
          grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
          gap: 15px;
          margin-bottom: 40px;
        }
        
        .gallery-item {
          cursor: pointer;
          border-radius: 8px;
          overflow: hidden;
        }
        
        .gallery-item img {
          width: 100%;
          height: 150px;
          object-fit: cover;
        }
        
        .gallery-item img:hover {
          opacity: 0.8;
        }
        
        .photo-display {
          max-width: 600px;
        }
        
        .photo-display img {
          view-transition-name: selected-photo;
          width: 100%;
          height: auto;
          border-radius: 12px;
        }
        
        ::view-transition-old(selected-photo) {
          animation: shrink-out 0.3s ease-out;
        }
        
        ::view-transition-new(selected-photo) {
          animation: grow-in 0.3s ease-in;
        }
        
        @keyframes shrink-out {
          from { transform: scale(1); opacity: 1; }
          to { transform: scale(0.8); opacity: 0; }
        }
        
        @keyframes grow-in {
          from { transform: scale(0.8); opacity: 0; }
          to { transform: scale(1); opacity: 1; }
        }
      </style>
    </head>
    <body>
      <div class="gallery-grid" id="gallery"></div>
      <div class="photo-display" id="photoDisplay"></div>
      
      <script>
        const photos = [
          { id: 1, src: 'photo1.jpg', title: 'Photo 1' },
          { id: 2, src: 'photo2.jpg', title: 'Photo 2' },
          { id: 3, src: 'photo3.jpg', title: 'Photo 3' },
          { id: 4, src: 'photo4.jpg', title: 'Photo 4' },
        ];
        
        function initGallery() {
          const gallery = document.getElementById('gallery');
          gallery.innerHTML = photos.map(photo => `
            <div class="gallery-item" data-id="${photo.id}">
              <img src="${photo.src}" alt="${photo.title}">
            </div>
          `).join('');
          
          gallery.addEventListener('click', (e) => {
            const item = e.target.closest('[data-id]');
            if (item) {
              selectPhoto(parseInt(item.dataset.id));
            }
          });
          
          // Display first photo
          selectPhoto(1);
        }
        
        function selectPhoto(photoId) {
          const photo = photos.find(p => p.id === photoId);
          if (!photo) return;
          
          if (document.startViewTransition) {
            document.startViewTransition(() => {
              displayPhoto(photo);
            });
          } else {
            displayPhoto(photo);
          }
        }
        
        function displayPhoto(photo) {
          const display = document.getElementById('photoDisplay');
          display.innerHTML = `
            <img src="${photo.src}" alt="${photo.title}">
            <h2>${photo.title}</h2>
          `;
        }
        
        // Initialize when page loads
        document.addEventListener('DOMContentLoaded', initGallery);
      </script>
    </body>
    </html>

    Resources and Further Reading

    If you want to dive deeper:


    In Summary

    The View Transitions API isn’t revolutionary in the sense that it does something that was impossible before. But it’s revolutionary in accessibility. It takes something that was hard and makes it trivial. It takes something that required expertise and opens it up to everyone.

    Here’s what actually matters:

    • You can create smooth animations in 3 lines of code instead of dozens
    • Browser support is actually pretty good right now
    • You can use it today with proper fallbacks
    • As browser support improves, your users automatically get better experiences

    The web is slowly becoming more polished. Interactions are getting smoother. Users are coming to expect that polish. View Transitions are a huge part of why that’s happening.

    If you’re building web applications, you should be using them. Not because they’re cutting-edge or trendy, but because they’re practical, they work, and they make your users’ experiences better with minimal effort on your part.

  • Hello world!

    Welcome to WordPress. This is your first post. Edit or delete it, then start writing!