View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Videos

Abrir menú Cerrar menú
  • Colecciones
  • Todos los videos
  • Información

Más videos

  • Información
  • Código
  • What's new for web developers

    Explore the latest features and improvements for Safari and WebKit. We'll walk you through updated web APIs, CSS and media features, JavaScript syntax, and more to help you build great experiences for people when they use your website, home screen web apps, or embedded WebKit views.

    Recursos

    • Safari Technology Preview
    • Safari Release Notes
    • WebKit Open Source Project
    • Web Inspector Reference
      • Video HD
      • Video SD

    Videos relacionados

    WWDC20

    • Discover WKWebView enhancements
    • Meet Face ID and Touch ID for the web
    • Meet Safari Web Extensions
    • What's new in Web Inspector
  • Buscar este video…
    • 4:22 - Web Animations API code example

      // Web Animations API Code Example
      
      let needle = document.getElementById("needle");
      let logo = document.getElementById("logo");
      logo.addEventListener("click", () => {
          needle.animate({
              transform: [
                  "rotateX(35deg) rotateZ(13deg)", 
                  "rotateX(35deg) rotateZ(733deg)",
              ],
              easing: ["ease-out"],
          }, 800);
      });
    • 6:43 - Resize observer example

      // Resize Observer Example
      
      let formatPanelObserver = new ResizeObserver((entries) => {
          entries.forEach((entry) => {
              let container = entry.target;
              container.classList.toggle("small", entry.contentRect.width < 175);
         }
      });
      
      formatPanelObserver.observe(document.getElementById("format-panel"));
    • 8:15 - Async Clipboard API plain text programmatic copy

      // Programmatic copy
      copyButtonElement.addEventListener("click", (event) => {
          navigator.clipboard.writeText("Plain text to copy.").then(() => {
             // Successful copy
          }, () => {
             // Copy failed
          });
      });
    • 8:22 - Async Clipboard API plain text examples

      // Programmatic copy
      copyButtonElement.addEventListener("click", (event) => {
          navigator.clipboard.writeText("Plain text to copy.").then(() => {
             // Successful copy
          }, () => {
             // Copy failed
          });
      });
      
      // Programmatic paste
      pasteButtonElement.addEventListener("click", (event) => {
          navigator.clipboard.readText().then((clipText) => {
              document.querySelector(".editor").innerText += clipText);
          });
      });
    • 10:25 - Web Component example markup

      <template id="format-button">
          <button class="format">
              <span class="icon"></span>
              <span class="label"></span>
          </button>
      </template>
    • 10:36 - Registering the Web Component

      let template = document.getElementById("format-button");
      window.customElements.define(template.id, class extends HTMLElement {
          constructor() {
              super();
      
              this.attachShadow({mode: "open"});
              let newButtonElement = template.content.cloneNode(true);
      
              let parts = newButtonElement.querySelectorAll("span");
              parts[0].textContent = this.getAttribute("data-icon");
              parts[1].textContent = this.textContent;
      
              this.shadowRoot.appendChild(newButtonElement);
              this.addEventListener("click", this.handleClick.bind(this));
          }
      });
    • 11:02 - Web Component custom elements

      <format-button id="bold" data-icon="B">Bold</format-button>
      <format-button id="italic" data-icon="I">Italic</format-button>
      <format-button id="underline" data-icon="U">Underline</format-button>
      <format-button id="strikethrough" data-icon="S">Strikethrough</format-button>
      <format-button id="paste" data-icon="&#x1f4cb;">Paste</format-button>
    • 12:28 - Original example Web Component template

      <template id="format-button">
          <button class="format">
              <span class="icon"></span>
              <span class="label"></span>
          </button>
      </template>
    • 12:30 - Example Web Component template with CSS Shadow Parts

      <template id="format-button">
          <button class="format">
              <span part="icon" class="icon"></span>
              <span part="label" class="label"></span>
          </button>
      </template>
    • 12:38 - CSS Shadow Part styles

      #bold::part(icon) {
          color: var(--formatting-button-icon-color);
          font-weight: bold;
      }
      
      #italic::part(icon) {
          color: var(--formatting-button-icon-color);
          font-style: italic;
      }
      
      #underline::part(icon) {
          color: var(--formatting-button-icon-color);
          text-decoration: underline;
      }
    • 13:16 - HTML enterkeyhint attribute

      <div id="editor" contenteditable="true" enterkeyhint="send"></div>
    • 14:32 - System font families

      font-family: system-ui;
      font-family: ui-sans-serif;
      font-family: ui-serif;
      font-family: ui-monospace;
      font-family: ui-rounded;
    • 14:45 - San Francisco font family

      body {
          font-family: system-ui;
          font-family: ui-sans-serif;
      }
    • 14:53 - New York font family

      body {
         font-family: ui-serif;
      }
    • 14:58 - SF Mono font family

      body {
         font-family: ui-monospace;
      }
    • 15:03 - SF Rounded font family

      body {
         font-family: ui-rounded;
      }
    • 16:07 - line-break: auto

      code {
          line-break: auto;
      }
    • 16:43 - line-break: anywhere

      code {
          line-break: anywhere;
      }
    • 17:25 - Removing margins from subsequent headings

      h1, h2, h3, h4, h5, h6 {
          margin-top: 3em;
      }
      
      h1 + h2,
      h2 + h3,
      h3 + h4,
      h4 + h5,
      h5 + h6 {
          margin-top: 0;
      }
    • 17:56 - Removing margins from any subsequent headings

      h1, h2, h3, h4, h5, h6 {
          margin-top: 3em;
      }
      
      h1 + h2, h1 + h3, h1 + h4, h1 + h5, h1 + h6,
      h2 + h3, h2 + h3, h2 + h4, h2 + h5, h2 + h6,
      h3 + h4, h3 + h3, h3 + h4, h3 + h5, h3 + h6,
      h4 + h5, h4 + h3, h4 + h4, h4 + h5, h4 + h6,
      h5 + h6, h5 + h3, h5 + h4, h5 + h5, h5 + h6 {
          margin-top: 0;
      }
    • 18:02 - Using :is() to remove margins from subsequent headings

      h1, h2, h3, h4, h5, h6 {
          margin-top: 3em;
      }
      
      :is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
          margin-top: 0;
      }
    • 18:31 - :is() specificity prevents the override from working

      :is(.intro, .pullquote, #hero) + p {
          text-transform: uppercase;
      }
      
      h2 + p,
      h3 + p,
      h4 + p,
      h5 + p,
      h6 + p {
          text-transform: none;
      }
    • 19:07 - :where () resets specificity

      :where(.intro, .pullquote, #hero) + p {
          text-transform: uppercase;
      }
      h2 + p,
      h3 + p,
      h4 + p,
      h5 + p,
      h6 + p {
          text-transform: none;
      }
    • 19:53 - WebP graceful fallback to JPG

      <picture>
        <source srcset="example.webp" type="image/webp">
        <img src="example.jpg" alt="Example Image">
      </picture>
    • 19:54 - WebP graceful fallback to JPG and server-side detection

      <picture>
        <source srcset="example.webp" type="image/webp">
        <img src="example.jpg" alt="Example Image">
      </picture>
      
      Accept: image/webp,image/png,image/svg+xml,image/*;…
    • 21:17 - Image with no size attributes

      <img src="MexicoCity.png">
    • 21:19 - Image with size attributes

      <img src="MexicoCity.png" width="560" height="747">
    • 21:49 - Respect EXIF image orientation default behavior

      image-orientation: from-image;
    • 22:13 - Override image orientation to use the raw image capture

      image-orientation: none;
    • 22:37 - HDR display CSS media query

      <style>
      @media only screen (dynamic-range: high) {
          /* HDR-only CSS rules */
      }
      </style>
    • 22:42 - HDR display CSS media query and JavaScript matchMedia detection

      <style>
      @media only screen (dynamic-range: high) {
          /* HDR-only CSS rules */
      }
      </style>
      
      <script>
      if (window.matchMedia("dynamic-range: high")) {
          // HDR-specific JavaScript
      }
      </script>
    • 23:19 - Remote Playback API example

      <video id="videoElement" src="https://site.example/video.mp4"></video>
      <button id="deviceButton">Send video to a remote device</button>
      
      <script>
          let videoElement = document.getElementById("videoElement");
          let deviceButton = document.getElementById("deviceButton");
          deviceButton.addEventListener("click", (event) => {
              videoElement.remote.prompt().then(updateRemotePlaybackState);
          });
      </script>
    • 24:20 - Picture in Picture example

      <video id="videoElement" src="https://site.example/video.mp4"></video>
      <button id="pipButton">Enter picture-in-picture mode</button>
      
      <script>
          let videoElement = document.getElementById("videoElement");
          let pipButton = document.getElementById("pipButton");
          pipButton.addEventListener("click", (event) => {
              videoElement.requestPictureInPicture().then(handlePictureInPicture);
          });
      </script>
    • 27:11 - BigInt example with division examples

      let bigInt = BigInt(Number.MAX_SAFE_INTEGER);
      // 9007199254740991n
      
      console.log(8n / 2n);
      // 4n
      
      console.log(9n / 2n);
      // 4n
    • 28:02 - Nullish coalescing operator

      class Person {
          constructor(firstName, lastName, age) {
              this.firstName = firstName ?? "Unknown";
              this.lastName = lastName ?? "Unknown";
              this.age = age ?? NaN;
         }
      }
      
      console.log(new Person());  
      // { firstName: "Unknown", lastName: "Unknown", age: NaN }
      
      console.log(new Person(false, false, true));
      // { firstName: false, lastName: false, age: true }
      
      console.log(new Person("John", "", 0));  
      // { firstName: "John", lastName: "", age: 0 }
      
      console.log(new Person("John", "Appleseed", 42));  
      // { firstName: "John", lastName: "Appleseed", age: 42 }
    • 29:09 - JavaScript optional chaining example

      class Person {
          constructor(firstName, lastName, age) {
              this.firstName = firstName ?? "Unknown";
              this.lastName = lastName ?? "Unknown";
              this.age = age ?? NaN;
              this.name = { firstName: this.firstName, lastName: this.lastName };
        }
      }
      
      function register(person) {
          // Before optional chaining
          if (person !== undefined && person.name !== undefined)
              console.log(person.name.firstName);
      }
      
      register(new Person());
      // undefined
      
      register(new Person("John", "Appleseed"));
      // "John"
    • 29:41 - JavaScript optional chaining example

      class Person {
          constructor(firstName, lastName, age) {
              this.firstName = firstName ?? "Unknown";
              this.lastName = lastName ?? "Unknown";
              this.age = age ?? NaN;
              this.name = { firstName: this.firstName, lastName: this.lastName };
        }
      }
      
      function register(person) {
          // With optional chaining
          console.log(person?.name.firstName);
      }
      
      register(new Person());
      􀆊 undefined
      
      register(new Person("John", "Appleseed"));
      􀆊 "John"
    • 29:49 - JavaScript optional chaining with indexes

      // Without optional chaining
      console.log(person.children[0]);
      // TypeError: undefined is not an object
      
      // With optional chaining
      console.log(person.children?.[0]);
      // undefined
    • 30:02 - JavaScript optional chaining with methods

      // Without optional chaining
      console.log(person.fullName());
      􀆊 TypeError: person.fullName is not a function.
      
      // With optional chaining
      console.log(person.fullName?.());
      􀆊 undefined
    • 30:23 - Logical assignment operators

      a &&= b // and assignment operator
      a ||= b // or assignment operator
      a ??= b // nullish assignment operator
    • 30:44 - Nullish coalescing approach

      // Nullish coalescing approach
      element.innerHTML = element.innerHTML ?? "Hello World!"
    • 30:52 - Logical assignment operator

      a &&= b // and assignment operator
      a ||= b // or assignment operator
      a ??= b // nullish assignment operator
      
      // Nullish coalescing approach
      element.innerHTML = element.innerHTML ?? "Hello World!"
      
      // Logical assignment operator
      element.innerHTML ??= "Hello World!"
    • 30:53 - Public class fields

      class Person {
          firstName = "";
          lastName = "";
          age = NaN;
          children = [];
      
          constructor(firstName, lastName, age) {
              this.firstName = firstName ?? "Unknown";
              this.lastName = lastName ?? "Unknown";
              this.age = age ?? NaN;
          }
      }
    • 31:58 - String.prototype.replace example

      "This doesn't work, and doesn't make sense".replace ("doesn't", "does");
      › This does work, and doesn't make sense
    • 32:09 - String.prototype.replaceAll example

      "This doesn't work, and doesn't make sense".replaceAll("doesn't",
      "does");
      › This does work, and does make sense
    • 33:53 - App Clips banner

      <meta name="apple-itunes-app"
            content="app-id=myAppStoreID,
                     app-clip-bundle-id=clipBundleID,
                     affiliate-data=myAffiliateData,
                     app-argument=myURL">

Developer Footer

  • Videos
  • WWDC20
  • What's new for web developers
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines