You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端浏览器专属Mychordbook吉他/尤克里里弦随机CSS故障修复求助

Troubleshooting Mobile iOS String Rendering Glitches in Mychordbook

First off, this sounds like a classic iOS Safari/Chrome rendering quirk—those thin 1px elements combined with rapid class transitions are triggering subpixel rendering or compositing layer bugs, which are common in older iOS versions like 14.0.1. Let’s walk through targeted fixes based on your code and the symptoms you described:

1. Fix Hardware Acceleration & Compositing Layers

iOS browsers sometimes struggle to render elements that aren’t properly promoted to their own compositing layers. Try forcing the strings and their container into hardware-accelerated layers to prevent the white glitches:

Update your .guitar .string CSS:

.guitar .string {
  position: absolute;
  left: 0;
  width: 100%;
  background-color: black;
  z-index: 1;
  /* Add these lines to force hardware acceleration */
  transform: translateZ(0);
  will-change: background-color;
}

You can also add the same transform to the parent instrument container to ensure it’s a stable stacking context:

.guitar {
  transform: translateZ(0);
  overflow: hidden; /* Prevents any overflow artifacts from bleeding through */
}

2. Adjust Thin String Sizing to Avoid Subpixel Bugs

The 1px height with -0.5px margin-top is likely causing subpixel rendering issues on Retina displays. Instead of using height and negative margins, try using a border to draw the string—iOS handles border rendering more consistently for thin lines:

.guitar .string {
  position: absolute;
  left: 0;
  width: 100%;
  z-index: 1;
  transform: translateZ(0);
  will-change: border-color;
  /* Remove height, background, and negative margin */
  border-top: 1px solid black;
  margin-top: 0;
}

.guitar .string.active {
  border-top-color: white; /* Toggle border color instead of background */
}

/* Adjust top positions to account for border (no more negative margin) */
.guitar .string[data-string='1'] {
  top: 8.333%;
}
.guitar .string[data-string='2'] {
  top: 25%;
}

This eliminates the subpixel margin that might be causing white artifacts to bleed through to underlying text.

3. Sync Animations with Browser Repaint Cycle

Your setTimeout calls might be out of sync with the browser’s repaint schedule, leading to visual glitches. Replace them with requestAnimationFrame to ensure class changes happen at the right time:

function play_string(inst, string) {
  const string_played = $instruments[inst].$strings[string-1];
  const pick_played = $instruments[inst].$picks[string - 1];

  // Reset transitions first
  string_played.classList.remove('transition');
  pick_played.classList.remove('transition');

  // Trigger playing state in sync with repaint
  requestAnimationFrame(() => {
    string_played.classList.add('playing');
    pick_played.classList.add('playing');
  });

  // Add transition after one frame
  setTimeout(() => {
    requestAnimationFrame(() => {
      string_played.classList.add('transition');
      pick_played.classList.add('transition');
    });
  }, 100);

  // Remove playing state after transition
  setTimeout(() => {
    requestAnimationFrame(() => {
      string_played.classList.remove('playing');
      pick_played.classList.remove('playing');
    });
  }, 200);
}

This ensures the browser has time to repaint before applying transitions, reducing the chance of rendering artifacts.

4. Verify Stacking Contexts

Even with z-index:1, if a parent element creates a new stacking context (e.g., using transform, opacity, or position:relative without a z-index), your strings might be rendered under unexpected elements. Double-check that:

  • The .guitar container has position: relative (or absolute/fixed) to establish a stacking context for the strings.
  • No parent elements of the strings have opacity set below 1, which can create a new stacking context and interfere with z-index.

5. Test with CSS Animations Instead of Class Toggles

If class toggles are still causing issues, try replacing JS timing with a CSS keyframe animation. This lets the browser handle animation timing more reliably:

Add this CSS:

@keyframes stringPlay {
  0% { background-color: black; }
  50% { background-color: white; }
  100% { background-color: black; }
}

.guitar .string.playing {
  animation: stringPlay 200ms linear forwards;
  /* Remove transition class since we're using keyframes */
}

Then simplify your JS:

function play_string(inst, string) {
  const string_played = $instruments[inst].$strings[string-1];
  const pick_played = $instruments[inst].$picks[string - 1];

  // Reset animation by removing and re-adding the class
  string_played.classList.remove('playing');
  pick_played.classList.remove('playing');
  
  requestAnimationFrame(() => {
    string_played.classList.add('playing');
    pick_played.classList.add('playing');
  });
}

This avoids manual setTimeout calls and leverages the browser’s native animation engine, which is more stable on iOS.

Start with the compositing layer fix (transform: translateZ(0)) as it’s the quickest to test, then move to the string sizing adjustment if needed. These changes should target the underlying rendering bugs causing your white glitches and text bleed-through.

内容的提问来源于stack exchange,提问作者Giray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 13:53:11