AboutBlogContact
Backend EngineeringSeptember 14, 2007 7 min read 125Updated: May 18, 2026

The iPhone Problem: Every Website Broke on June 29, 2007

AunimedaAunimeda
📋 Table of Contents

The iPhone Problem: Every Website Broke on June 29, 2007

Before June 29, 2007, "mobile web" meant WAP: stripped-down pages with no CSS, no images, designed for Nokia feature phones with 128×160 pixel screens. Nobody expected WAP sites to look like real websites. Developers built for desktop and put up a separate m.site.com for mobile if they could afford to.

The iPhone changed the expectation overnight. It ran Safari on WebKit - a real, modern browser. Steve Jobs demonstrated it loading the actual New York Times website, not a mobile-adapted version. He called it "the internet in your pocket." Users believed him.

The problem: that New York Times website was designed for an 1024×768 viewport. On a 320×480 screen, Safari rendered it at 980px wide and then zoomed out to fit. Every website became a tiny, unreadable thumbnail that users had to pinch-to-zoom to read anything.

We had work to do.


What the iPhone Browser Actually Was

Safari on iPhone used WebKit, the same engine as Safari on Mac. WebKit's CSS support in 2007 was ahead of Firefox and far ahead of IE. The HTML parser was modern. JavaScript ran via Nitro (not yet), just the regular JavaScriptCore - slow by today's standards, but functional.

The iPhone viewport was 320px wide (in portrait) / 480px wide (in landscape). But Safari's default behavior was to set a viewport of 980px and scale down to fit. This showed the full desktop site, shrunk.

Apple introduced the <meta name="viewport"> tag specifically for iPhone:

<!-- Without this: Safari renders at 980px and scales to fit the screen -->
<!-- With this: Safari uses the device's actual pixel width -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- Lock the scale (prevent user zoom - controversial, but used by apps) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0,
      maximum-scale=1.0, user-scalable=no">

<!-- For web apps that wanted to look like native apps -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

The viewport meta tag was Apple's invention, not a web standard. It became a de facto standard when Android adopted it, and was standardized by the W3C years later.


Detecting the iPhone in 2007

CSS media queries as we know them didn't work in 2007. CSS2 had @media screen and @media print. The width media feature wasn't widely supported. iPhone detection was done via JavaScript:

// iPhone detection - 2007 approach
// User-agent sniffing: ugly but the only option

function isiPhone() {
    return navigator.userAgent.match(/iPhone/i) !== null;
}

function isiPod() {
    return navigator.userAgent.match(/iPod/i) !== null;
}

function isMobileApple() {
    return isiPhone() || isiPod();
}

// Redirect to mobile version
if (isMobileApple()) {
    // Only redirect if not already on mobile subdomain
    if (window.location.hostname.indexOf('m.') === -1) {
        window.location.href = 'http://m.' +
            window.location.hostname +
            window.location.pathname;
    }
}

The m. subdomain pattern became ubiquitous in 2007-2012: m.twitter.com, m.facebook.com, m.cnn.com. It was technically straightforward - a separate site, optimized for 320px screens - and architecturally a disaster. Two codebases. Two sets of URLs. Content out of sync. SEO split.


Building a Proper iPhone-Optimized Page (2007)

The correct 2007 approach - building a page that worked well on iPhone without a separate subdomain:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>iPhone-Compatible Site</title>

  <!-- The critical viewport tag -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <!-- iPhone home screen icon (57×57 PNG) -->
  <link rel="apple-touch-icon" href="/images/apple-touch-icon.png">

  <style type="text/css">
  /* Default: desktop layout */
  body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
  }

  #wrapper {
      width: 960px;
      margin: 0 auto;
  }

  #sidebar { float: right; width: 200px; }
  #main    { margin-right: 220px; }

  /*
   * CSS2 media type for screen size:
   * "handheld" type existed but iPhone IGNORED it - it identified as "screen"
   * Safari on iPhone: screen + 320px wide
   *
   * The hack: target small screens by max-width
   * CSS3 media queries weren't widely supported in 2007,
   * but WebKit/Safari supported them early.
   */

  @media screen and (max-width: 480px) {
      /* iPhone-specific overrides */
      #wrapper { width: 100%; }
      #sidebar { display: none; }     /* hide sidebar on mobile */
      #main    { margin-right: 0; }

      /* Larger tap targets - fingers are 44px minimum comfortable tap size */
      a, button {
          display: block;
          padding: 10px;
          font-size: 16px;   /* prevent iPhone auto-zoom on focus */
          /* iPhone auto-zoomed input fields to 16px unless font was 16px+ */
      }

      /* Navigation: horizontal tabs become vertical list */
      #nav ul {
          padding: 0;
          margin: 0;
      }

      #nav li {
          display: block;
          border-bottom: 1px solid #ccc;
      }

      #nav li a {
          display: block;
          padding: 12px 16px;
          text-decoration: none;
          font-size: 17px;
          /* 17px = iOS native list item font size */
      }

      /* Images: don't overflow the screen */
      img {
          max-width: 100%;
          height: auto;
      }

      /* Tables: the most broken thing on mobile */
      table {
          width: 100%;
          display: block;
          overflow-x: auto;   /* horizontal scroll rather than overflow */
      }
  }
  </style>
</head>
<body>
  <!-- Touch events: iPhone didn't fire click events on non-interactive elements
       Solution: make elements interactive via onclick="" or cursor:pointer -->
  <div id="nav">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
  </div>
</body>
</html>

The 16px Font Rule and Auto-Zoom

One iPhone behavior in 2007 that drove developers insane: Safari would automatically zoom into any <input> element that had a font smaller than 16px when the user tapped it. This was intended to help readability but destroyed form layouts.

/* The iPhone form fix - 2007 */
/* Set all inputs to 16px to prevent auto-zoom on focus */

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
textarea,
select {
    font-size: 16px;  /* Magic number - below 16px triggers Safari zoom */
}

This behavior persists in Safari on iOS today, seventeen years later.


Touch Events: The New Event Model

iPhone introduced a new set of DOM events that didn't exist on desktop:

// Touch events - new in 2007, no browser had these before iPhone

document.addEventListener('touchstart', function(e) {
    var touch = e.touches[0];
    console.log('Touch start at: ' + touch.clientX + ', ' + touch.clientY);
});

document.addEventListener('touchmove', function(e) {
    e.preventDefault(); // Prevent native scroll - for custom scroll implementations
    var touch = e.touches[0];
});

document.addEventListener('touchend', function(e) {
    var touch = e.changedTouches[0];
    // Use changedTouches - touches array is empty on touchend
});

// 300ms click delay problem:
// iPhone waited 300ms after a tap to fire the 'click' event
// to distinguish single-tap from double-tap (double-tap = zoom)
// Solution in 2007: use touchend instead of click for mobile

function fastClick(element, callback) {
    var startX, startY;

    element.addEventListener('touchstart', function(e) {
        startX = e.touches[0].clientX;
        startY = e.touches[0].clientY;
    });

    element.addEventListener('touchend', function(e) {
        var endX = e.changedTouches[0].clientX;
        var endY = e.changedTouches[0].clientY;

        // Only fire if finger didn't move (wasn't a scroll)
        if (Math.abs(endX - startX) < 10 && Math.abs(endY - startY) < 10) {
            e.preventDefault();
            callback.call(this, e);
        }
    });
}

The 300ms click delay was a real performance issue. The fastclick.js library (released 2013) existed entirely to solve this one problem. It was removed from browsers starting with Chrome 32 (2014) when the touch-action: manipulation CSS property was implemented. A seven-year saga from a single iPhone behavior.


What the iPhone Actually Changed

The iPhone did not just add a new device category. It changed the performance and interaction expectations for the entire web:

Touch targets. Physical buttons are precisely clickable. Fingers are not. Apple's human interface guidelines specified 44×44pt as the minimum tap target. Web buttons designed for mouse clicks - often 24px tall links - became unusable on touchscreens.

Network expectations. iPhone's EDGE data connection was 150-200 kbps. Page weight that was acceptable on ADSL - 500KB pages - meant 20-second load times on EDGE. Mobile performance optimization became a discipline.

The m. subdomain was wrong. The industry built separate mobile sites for 2007-2012 and spent 2012-2016 tearing them down and building responsive designs. The m. approach created URL fragmentation and two maintenance burdens. The right answer - fluid layouts + media queries - wasn't fully embraced until Ethan Marcotte named "Responsive Web Design" in 2010.

The iPhone in 2007 was the loudest possible signal: the web is not a desktop-only medium. We needed five more years to fully internalize it.


Aunimeda builds production-grade backend systems - APIs, microservices, real-time applications, and system integrations.

Contact us for backend engineering services. See also: Custom Software Development, Web Development

Read Also

Node.js: Ryan Dahl's 45-Minute Talk That Rewrote Backend Development (2009)aunimeda
Backend Engineering

Node.js: Ryan Dahl's 45-Minute Talk That Rewrote Backend Development (2009)

On November 8, 2009, Ryan Dahl presented Node.js at JSConf EU in Berlin. He showed JavaScript running on the server with non-blocking I/O. The audience sat in silence, then gave a standing ovation. Within three years, Node.js had more packages than any other programming language ecosystem. This is what he built and why it worked.

Google Chrome and V8: The Day JavaScript Got Fast (2008)aunimeda
Backend Engineering

Google Chrome and V8: The Day JavaScript Got Fast (2008)

On September 2, 2008, Google released Chrome 0.2 with the V8 JavaScript engine. V8 compiled JavaScript directly to native machine code. Benchmarks showed it 10-50x faster than IE7. Within eighteen months, every browser had raced to match it. JavaScript performance went from a constant limitation to a solved problem.

Ajax: The Name That Changed How We Think About the Web (2005)aunimeda
Backend Engineering

Ajax: The Name That Changed How We Think About the Web (2005)

On February 18, 2005, Jesse James Garrett published 'Ajax: A New Approach to Web Applications.' The technology was not new - XMLHttpRequest had existed since 1999. What Garrett gave the industry was a name, a mental model, and permission to rethink the web as an application platform.

Need IT development for your business?

We build websites, mobile apps and AI solutions. Free consultation.

Get Consultation All articles