Youtube Scrollable Right Side Description

Moves and expands YouTube description on the right, making it scrollable and dynamically adjusting height to video.

当前为 2025-04-14 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Youtube Scrollable Right Side Description
  3. // @description Moves and expands YouTube description on the right, making it scrollable and dynamically adjusting height to video.
  4. // @version 3.0
  5. // @author SH3LL
  6. // @license MIT
  7. // @match *://*.youtube.com/*
  8. // @grant none
  9. // @run-at document-end
  10. // @namespace https://gf.qytechs.cn/users/762057
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let descriptionExpander;
  17. const moveEl = (parent, child) => parent?.prepend(child);
  18. const setElStyle = (el, styles) => el?.setAttribute('style', styles);
  19. const qSel = sel => document.querySelector(sel);
  20. const getElById = id => document.getElementById(id);
  21.  
  22. const ownerObserver = new MutationObserver((mutationsList, observer) => {
  23. if (getElById('owner')) {
  24. observer.disconnect();
  25. console.log('"owner" found, executing.');
  26. executeScript();
  27. }
  28. });
  29. ownerObserver.observe(document.body, { childList: true, subtree: true });
  30.  
  31. const updateDescHeight = height => {
  32. descriptionExpander && (descriptionExpander.style.maxHeight = `${height - 70}px`);
  33. };
  34.  
  35. const videoHeightObserver = new MutationObserver(mutations => {
  36. for (const m of mutations) {
  37. if (m.type === 'attributes' && m.attributeName === 'style') {
  38. const heightMatch = m.target.style.height.match(/^(\d+)px$/);
  39. heightMatch && updateDescHeight(parseInt(heightMatch[1], 10));
  40. }
  41. }
  42. });
  43.  
  44. const observeVideoHeight = () => {
  45. const videoContent = qSel('.ytp-iv-video-content');
  46. if (videoContent) {
  47. videoHeightObserver.observe(videoContent, { attributes: true, attributeFilter: ['style'] });
  48. const initialHeight = videoContent.style.height.match(/^(\d+)px$/);
  49. initialHeight && updateDescHeight(parseInt(initialHeight[1], 10));
  50. } else {
  51. console.warn('No .ytp-iv-video-content found.');
  52. }
  53. };
  54.  
  55. function executeScript() {
  56. const related = qSel('#related');
  57. const bottomRow = getElById('bottom-row');
  58. const owner = getElById('owner');
  59. const below = qSel('#below');
  60. const infoContainer = getElById('info-container');
  61. descriptionExpander = getElById('description-inline-expander');
  62. const description = getElById('description');
  63. const descriptionInner = getElById('description-inner');
  64. const descStyle = `margin-left: 0; overflow: auto; max-width: 100%; font-size: 1.3rem; line-height: normal; width: auto; padding: 8px; border-bottom-width: 0; --yt-endpoint-text-decoration: underline; background-color: var(--yt-playlist-background-item)`;
  65.  
  66. moveEl(related, bottomRow);
  67. owner && (moveEl(related, owner), setElStyle(owner, 'margin:0'));
  68. moveEl(below, infoContainer);
  69. setElStyle(infoContainer, 'color:white; font-size: 12px');
  70.  
  71. if (descriptionExpander && description && descriptionInner) {
  72. setElStyle(descriptionExpander, descStyle);
  73. setElStyle(description, 'margin: 0');
  74. setElStyle(descriptionInner, 'margin: 0');
  75. descriptionExpander.setAttribute('is-expanded', '');
  76. observeVideoHeight();
  77. }
  78.  
  79. const removalObserver = new MutationObserver(mutations => {
  80. const targets = ['expand', 'collapse', 'ytd-watch-info-text', 'snippet'];
  81. for (const m of mutations) {
  82. if (m.type === 'childList') {
  83. targets.forEach(id => getElById(id)?.remove());
  84. !targets.some(getElById) && (observer.disconnect(), console.log('Removal observer done.'));
  85. }
  86. }
  87. });
  88.  
  89. const watchInfoFlex = qSel('ytd-watch-metadata > div');
  90. watchInfoFlex && removalObserver.observe(watchInfoFlex, { childList: true, subtree: true });
  91. }
  92. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址