没有不值得去解决的问题,也没有不值得去学习的技术!

Header Poetry Micro-Content System in Practice: Converging From Dynamic Animations to Stable Static Components

如图4:最终 Header 展示效果

作者:

在

🧭 1. Background: Adding a Poetry Microcontent Module to the WordPress Header

While optimizing the WordPress site header, I wanted to add a lightweight “cultural microcontent component” to display:

  • Tang poetry
  • Song poetry
  • Southern Tang poetry

The goals were:

✔ Do not affect layout
✔ Do not affect performance
✔ Maintain header stability
✔ Provide a subtle cultural atmosphere


Figure 1: Initial Row structure of the Header
Figure 1: Initial Row structure of the Header

🧪 2. Version One: Attempting CSS Animation for Scrolling Poetry

The initial implementation used CSS animation:

CSS
animation: poetryScroll 14s linear infinite;

And output the poetry via PHP:

PHP
return '<div class="poetry-marquee-wrapper">    <span class="poetry-marquee-static">' . esc_html($random) . '</span></div>';

⚠️ Issues Encountered:

  • ❌ Slight jitter in the Header layout
  • ❌ Unstable FSE Row structure
  • ❌ Abnormal truncation of long verses
  • ❌ Misalignment in different language environments
  • ❌ UI layer background conflicts

Figure 2: Abnormal effect in the animation version
Figure 2: Abnormal effect in the animation version

🧠 3. Key Decision: Abandoning Animation for a Static Component

Final conclusion:

❗The Header area is not suitable for complex animation components

Therefore, the overall approach converged to:

  • ❌ Remove animation
  • ✔ Switch to static display
  • ✔ Strengthen PHP content control


🧩 4. Final Implementation (Stable PHP Version)

PHP
function wp_header_poetry() {

    $files = [
        '唐诗' => WP_CONTENT_DIR . '/uploads/tangshi-sanbai-shou.json',
        '宋词' => WP_CONTENT_DIR . '/uploads/songci-sanbai-shou.json',
        '南唐' => WP_CONTENT_DIR . '/uploads/nantang.json',
    ];

    $pool = [];

    foreach ($files as $type => $file) {

        if (!file_exists($file)) continue;

        $json = file_get_contents($file);
        $data = json_decode($json, true);

        if (!is_array($data)) continue;

        foreach ($data as $item) {

            if (
                !isset($item['author'], $item['paragraphs']) ||
                !is_array($item['paragraphs']) ||
                empty($item['paragraphs'])
            ) {
                continue;
            }

            $author = trim($item['author']);

            $paragraphs = array_map('trim', $item['paragraphs']);
            $text = implode('', $paragraphs);

            // =========================
            // ✂️ 智能截断(优化体验)
            // =========================
            if (mb_strlen($text, 'UTF-8') > 60) {

                $text = mb_substr($text, 0, 60, 'UTF-8');

                $pos1 = mb_strrpos($text, '。', 0, 'UTF-8');
                $pos2 = mb_strrpos($text, ',', 0, 'UTF-8');

                $pos1 = ($pos1 === false) ? 0 : $pos1;
                $pos2 = ($pos2 === false) ? 0 : $pos2;

                $pos = max($pos1, $pos2);

                if ($pos > 30) {
                    $text = mb_substr($text, 0, $pos + 1, 'UTF-8');
                }
            }

            // =========================
            // 🏷 标题处理
            // =========================
            $title = ($type === '宋词')
                ? ($item['rhythmic'] ?? '')
                : ($item['title'] ?? '');

            $title = trim($title);

            // =========================
            // 🧱 拼接展示内容
            // =========================
            $display = "【{$type}】";

            if (!empty($title)) {
                $display .= "《{$title}》";
            }

            $display .= " {$author}:{$text}";

            if (mb_strlen($display, 'UTF-8') <= 90) {
                $pool[] = $display;
            }
        }
    }

    if (empty($pool)) {
        return '';
    }

    $random = $pool[array_rand($pool)];

    return '<div class="poetry-marquee-wrapper">
        <span class="poetry-marquee-static">' . esc_html($random) . '</span>
    </div>';
}

echo wp_header_poetry();

Figure 3: WPCode plugin configuration interface
Figure 3: WPCode plugin configuration interface

🎨 5. Final CSS (Stable Version)

CSS
.poetry-marquee-wrapper {
    display: inline-flex;
    align-items: center;
    padding: 0 10px;
    min-width: 0;
}

.poetry-marquee-static {
    font-size: 14px;
    line-height: 1;
    opacity: 0.75;

    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    min-width: 0;
}

.wp-block-group.is-layout-flex {
    align-items: center;
}

header.wp-block-template-part {
    box-sizing: border-box;
}

Figure 4: Final Header display effect
Figure 4: Final Header display effect

🧭 6. Final Layout Structure in the Theme Editor (After Correction)

The correct structure of the current Header in FSE:

Plaintext
Header (Template Part)
└── Group (Outer Container)
    └── Row (Flex Layout)
        ├── Poetry Shortcode(Left side)
        ├── Search(Right group)
        └── Language Switcher(Right group)

Key points:

  • ✔ The Row must be unified
  • ✔ Left and right alignment relies on flex
  • ✔ Poetry must be within the same Row

Figure 5: Final state of the FSE Row structure
Figure 5: Final state of the FSE Row structure

📦 7. Poetry Data Source (GitHub)

This system uses structured JSON poetry data:

  • Three Hundred Tang Poems
  • Three Hundred Song Poems
  • Southern Tang poetry

🔗 Data Source

Plaintext
https://github.com/chinese-poetry/chinese-poetry

📁 JSON Structure Explanation

JSON
{
  "author": "作者",
  "title": "标题(唐诗/南唐)",
  "rhythmic": "词牌名(宋词)",
  "paragraphs": [
    "诗句1",
    "诗句2"
  ]
}

🧠 Data Processing Rules

  • Concatenate paragraphs directly
  • Do not add extra punctuation (to avoid “。,” issues)
  • Automatically truncate to 60 characters
  • The Header only displays one entry

Figure 6: Screenshot of the GitHub data structure
Figure 6: Screenshot of the GitHub data structure

🚀 8. Engineering Convergence Summary

This implementation went through three phases:

1️⃣ Animation Phase

  • CSS marquee
  • Layout jitter
  • Unstable ❌

2️⃣ Debugging Phase

  • flex + padding + FSE adjustments
  • Increased complexity ❌

3️⃣ Convergence Phase (Final)

  • Static component ✔
  • PHP content control ✔
  • Minimized CSS ✔
  • Stable structure ✔

🧠 9. Final Conclusion

The core takeaway from this optimization is:

❗The Header area should prioritize stability over visual complexity

系列导航

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系