YouTube Live Borderless

Make YouTube Live Borderless

目前为 2023-01-03 提交的版本。查看 最新版本

  1. /* ==UserStyle==
  2. @name YouTube Live Borderless
  3. @version 0.3.0
  4. @namespace github.com/cyfung1031
  5. @license MIT
  6. @description Make YouTube Live Borderless
  7. @author CY Fung
  8. @supportURL https://github.com/cyfung1031/YouTube-Live-Borderless/
  9. @compatible edge Edge [Blink] >= 105; Stylus (Beta)
  10. @compatible chrome Chrome >= 105; Stylus (Beta); Chrome 101-104 requires "enable-experimental-web-platform-features"
  11. @compatible firefox FireFox >= 103; Stylus; layout.css.has-selector.enabled = true; note: some features might not be very stable!!
  12. @compatible opera Opera >= 91; Stylus (Beta)
  13. @compatible safari Safari >= 15.4; Stylus
  14. @preprocessor stylus
  15. @var select mode-for-two-col "Mode for Two Columns" {
  16. "Expanded Panel Only (Recommended)": "expanded-panel",
  17. "Expanded Live Chat Only": "expanded-live",
  18. "Expandable Live Chat Only": "expandable-live",
  19. "Always": "always"
  20. }
  21. @var select mode-for-single-col "Mode for Single Column" {
  22. "YouTube Mobile (Recommended)": "mobile",
  23. "Normal": "normal",
  24. "Disabled": "disabled"
  25. }
  26. @var checkbox no-masthead "Hide Top Masthead Bar" 0
  27. @var number masthead-hoverable-h "MastHead Hoverable (1 = always hide)" [4, 1, 8, 1]
  28. @var range primary-content-margin "Primary Content Margin" [24, 6, 48, 6, "px"]
  29. @var checkbox no-bottom-row "Hide Primary MetaInfo Bottom Row" 0
  30. @var range video-title-size "Video Title Size" [2.0, 1.0, 3.0, 0.2, "rem"]
  31. @var range min-below-area "Minimum area below video" [120, 10, 240, 10, 'px']
  32. @var number side-panel-width "Side Panel Width" [440, 320, 640, 20, "px"]
  33. @var checkbox no-round-border "No Round Border" 1
  34. @var checkbox disable-cinematics "Disable Cinematics Effect" 0
  35. @var number chat-zoom-for-mobile "Chat Zoom for Mobile" [1.0, 0.2, 1.8, 0.05]
  36. ==/UserStyle== */
  37. /*
  38.  
  39. "Fill up Chat Area (experimental)": "chat-fill-up",
  40. @var range chrome-bottom-bar-margin "Chrome Bottom Bar Margin" [12, 6, 48, 6, "px"]
  41.  
  42. Chrome Bottom Bar Margin is 12px only due to
  43.  
  44. MU = function(a) {
  45. var b = a.u.ag()
  46. , c = a.G.getVideoData().D
  47. , d = 0;
  48. a.u.ag() && a.u.Me() && (d = (a.G.fb().getPlayerSize().width - a.G.getVideoContentRect().width) / 2);
  49. return 12 * (c ? 0 : b ? 2 : 1) + d
  50. }
  51.  
  52. */
  53.  
  54. @-moz-document url-prefix("https://www.youtube.com/watch?v=") {
  55.  
  56. dummy() {
  57. // dummy
  58. border: 0;
  59. }
  60. masthead-hoverable-height=(masthead-hoverable-h - 1) * 2px
  61.  
  62. no-masthead-w=no-masthead //
  63. chrome-bottom-bar-margin=12px // this cannot be changed
  64.  
  65. single-col-mobile=0 //
  66. if mode-for-single-col=="mobile" {
  67. single-col-mobile=1 //
  68. if no-masthead==0 {
  69. no-masthead-w=2 //
  70. }
  71. }
  72. chat-zoom-for-mobile-enable = ((chat-zoom-for-mobile < 1) or (chat-zoom-for-mobile > 1))
  73.  
  74. content361(){
  75. // general fix
  76. ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy{
  77. min-height: unset;
  78. }
  79. #movie_player .ytp-cued-thumbnail-overlay-image {
  80. background-size: contain !important;
  81. }
  82. ytd-watch-flexy:not([is-two-columns_]) ytd-watch-metadata {
  83. padding-top: var(--ytd-margin-3x);
  84. }
  85. ytd-watch-flexy:not([is-two-columns_]):not([fullscreen]) #primary.ytd-watch-flexy {
  86. padding-top: 0;
  87. margin-top:0;
  88. }
  89. }
  90.  
  91. //
  92. contentNoMasthead() {
  93.  
  94. &,
  95. ytd-app,
  96. ytd-page-manager[class].style-scope,
  97. ytd-watch-flexy[class].style-scope {
  98. /* 0px not 0 */
  99. --ytd-masthead-height: 0px;
  100. --ytd-toolbar-height: 0px;
  101. --ytd-watch-flexy-masthead-height: 0px;
  102. }
  103.  
  104. #masthead-container {
  105. height: 0;
  106. --masthead-opacity: 0;
  107. opacity: var(--masthead-opacity) !important;
  108. transition: opacity 300ms;
  109. min-height: masthead-hoverable-height;
  110. contain: layout size style;
  111. }
  112.  
  113. #masthead-container > ytd-masthead {
  114. transform: translateY(-100%);
  115. transition: transform 300ms;
  116. }
  117.  
  118. if masthead-hoverable-height > 0 {
  119.  
  120.  
  121. #masthead-container:hover {
  122. --masthead-opacity: 1;
  123. }
  124.  
  125. #masthead-container:hover > ytd-masthead {
  126. transform: translateY(0%);
  127. }
  128.  
  129. #masthead-container::after {
  130. content: '';
  131. display: flex;
  132. width: 100%;
  133. height: masthead-hoverable-height;
  134. top: 0;
  135. z-index: 77;
  136. cursor: default;
  137. user-select: none !important;
  138. touch-action: none !important;
  139. box-sizing: border-box;
  140. padding: 0;
  141. margin: 0;
  142. }
  143. }
  144.  
  145. ytd-watch-flexy.style-scope[is-two-columns_]:not([fullscreen]):not([theater]) {
  146.  
  147. #columns.style-scope.ytd-watch-flexy,
  148. #primary.style-scope.ytd-watch-flexy,
  149. #primary-inner.style-scope.ytd-watch-flexy,
  150. #secondary.style-scope.ytd-watch-flexy,
  151. #secondary-inner.style-scope.ytd-watch-flexy {
  152. height: 100vh;
  153. max-height: 100%;
  154. }
  155. }
  156.  
  157. ytd-watch-flexy.style-scope[is-two-columns_][theater]:not([fullscreen]) {
  158.  
  159. height: 100vh;
  160. #player-theater-container.ytd-watch-flexy {
  161. flex: 77;
  162. max-height: unset;
  163. }
  164.  
  165. #player-theater-container.ytd-watch-flexy ~ #columns.style-scope.ytd-watch-flexy {
  166. overflow: visible;
  167. }
  168. }
  169.  
  170.  
  171. ytd-watch-flexy.style-scope:not([fullscreen]) {
  172.  
  173. #movie_player .html5-video-container > video[style*="top:"]:not(video[style*="top: -"]):not(video[style*="top:-"]) {
  174. top: 0 !important;
  175. }
  176. }
  177. } //
  178. contentSingleColMobile(){
  179. // html:has(ytd-watch-flexy:not([is-two-columns_]):not([fullscreen]))
  180.  
  181. #chat:not([collapsed]) {
  182. --ytd-margin-2x: 0;
  183. --ytd-margin-4x: 0;
  184. --ytd-margin-6x: 0;
  185. --ytd-margin-8x: 0;
  186. height: 100% !important;
  187. min-height: unset !important;
  188. max-height: 100vh !important;
  189.  
  190. --single-col-mobile-below-inside-display: flex;
  191.  
  192.  
  193.  
  194. if chat-zoom-for-mobile-enable {
  195.  
  196.  
  197. iframe#chatframe {
  198. iframe-transform = 'scale(%s)' % chat-zoom-for-mobile
  199. iframe-ratio = 100% / chat-zoom-for-mobile
  200. transform: iframe-transform;
  201. height: iframe-ratio;
  202. position: absolute;
  203. /* max-height: unset !important; */
  204. transform-origin: 0 0;
  205. width: iframe-ratio;
  206. }
  207.  
  208.  
  209. }
  210.  
  211.  
  212. }
  213.  
  214. &:has(#chat:not([collapsed])) {
  215.  
  216. #contentContainer.tp-yt-app-drawer[swipe-open].tp-yt-app-drawer::after {
  217.  
  218. content: unset;
  219.  
  220. }
  221.  
  222. #primary-inner.ytd-watch-flexy ytd-comments#comments.ytd-watch-flexy,
  223. #below.ytd-watch-flexy > #related.ytd-watch-flexy,
  224. #below.ytd-watch-flexy > ytd-watch-metadata.ytd-watch-flexy {
  225. display:none !important;
  226. }
  227.  
  228. #secondary.ytd-watch-flexy {
  229. display: none !important;
  230. }
  231.  
  232.  
  233.  
  234. .efyt-control-bar {
  235. position: relative;
  236. display: inline-flex;
  237. top: auto;
  238. left: auto;
  239. z-index: 99999;
  240. opacity: 0.8;
  241. transform: translate(calc(-100% + 32px), 0) !important;
  242. }
  243.  
  244. .efyt-control-bar:hover {
  245. opacity: 1.0;
  246. background: var(--yt-spec-general-background-a);
  247. transform: translate(0px, 0) !important;
  248. }
  249.  
  250. #player {
  251. margin-bottom: 0;
  252. }
  253.  
  254. #columns,
  255. #primary {
  256. padding: 0;
  257. }
  258.  
  259. #player,
  260. #player-theater-container,
  261. #player-container-outer,
  262. #player-container-inner,
  263. #player-container,
  264. #movie_player,
  265. #movie_player video {
  266. object-fit: contain;
  267. max-height: calc(100vh - 400px) !important;
  268. }
  269.  
  270. #primary-inner.ytd-watch-flexy > :not(.style-scope) {
  271. display: none !important;
  272. }
  273.  
  274.  
  275. #below > * {
  276. display: var(--single-col-mobile-below-inside-display) !important;
  277. }
  278.  
  279. #below:not(:has(#chat)) {
  280. display: none;
  281. }
  282.  
  283. ytd-watch-flexy,
  284. #columns.ytd-watch-flexy,
  285. #primary.ytd-watch-flexy,
  286. #primary-inner.ytd-watch-flexy {
  287. display: flex;
  288. flex-direction: column;
  289. margin: 0;
  290. flex: 1;
  291. }
  292.  
  293. #below {
  294. flex: 1;
  295. }
  296.  
  297. ytd-watch-flexy {
  298. height: 100vh !important;
  299. max-height: 100vh !important;
  300. }
  301.  
  302. ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy,
  303. ytd-watch-flexy[fullscreen] #player-theater-container.ytd-watch-flexy {
  304.  
  305. min-height: unset !important;
  306. }
  307. }
  308. }
  309. contentf() {
  310.  
  311.  
  312. &:not([tabview-loaded]) {
  313.  
  314. #primary-inner.ytd-watch-flexy ytd-comments#comments.ytd-watch-flexy,
  315. #secondary-inner.ytd-watch-flexy > #related.ytd-watch-flexy {
  316. display: none !important;
  317. }
  318.  
  319. #player-theater-container {
  320. max-height: calc(100vh - 100px) !important;
  321. }
  322.  
  323. #cinematics {
  324. // contain: layout;
  325. contain: layout size style;
  326. user-select: none;
  327. touch-action: none;
  328. pointer-events: none;
  329. }
  330. }
  331.  
  332.  
  333. if no-masthead-w==2 {
  334. //
  335. } else if no-masthead-w==1 {
  336.  
  337. contentNoMasthead()
  338. }
  339.  
  340. else {
  341.  
  342. ytd-watch-flexy.style-scope[is-two-columns_]:not([theater]):not([fullscreen]) {
  343.  
  344. #secondary.style-scope.ytd-watch-flexy,
  345. #secondary-inner.style-scope.ytd-watch-flexy {
  346. height: calc(100vh - var(--ytd-toolbar-height));
  347. max-height: 100%;
  348. }
  349. }
  350. }
  351.  
  352.  
  353.  
  354. if no-bottom-row {
  355.  
  356. #bottom-row.ytd-watch-metadata {
  357. display: none !important;
  358. }
  359. }
  360.  
  361. h1.ytd-watch-metadata {
  362. font-size: video-title-size;
  363. --font-size: video-title-size;
  364. line-height: calc(var(--font-size) * 1.4);
  365. }
  366.  
  367. & {
  368. --ylb-min-below-area: min-below-area;
  369. }
  370. ytd-watch-flexy[is-two-columns_]:not([fullscreen]) #movie_player {
  371. .ytp-chrome-bottom[style*="width"] {
  372. width: unset !important;
  373. left: chrome-bottom-bar-margin !important;
  374. right: chrome-bottom-bar-margin !important;
  375. }
  376.  
  377. }
  378. ytd-watch-flexy:not([is-two-columns_]):not([fullscreen]) #movie_player {
  379. .ytp-chrome-bottom[style*="width"] {
  380. left: 50% !important;
  381. transform: translateX(-50%);
  382. }
  383.  
  384. }
  385.  
  386. ytd-watch-flexy.style-scope:not([fullscreen]) {
  387.  
  388. & {
  389. --ytd-margin-2y: var(--ytd-margin-2x);
  390. --ytd-margin-4y: var(--ytd-margin-4x);
  391. --ytd-margin-6y: var(--ytd-margin-6x);
  392. --ytd-margin-8y: var(--ytd-margin-8x);
  393. }
  394.  
  395. #columns.style-scope.ytd-watch-flexy {
  396. --ytd-margin-2x: 0;
  397. --ytd-margin-4x: 0;
  398. --ytd-margin-6x: 0;
  399. --ytd-margin-8x: 0;
  400. }
  401.  
  402. .style-scope.ytd-watch-flexy > :not(.ytd-watch-flexy),
  403. #below,
  404. #player {
  405. --ytd-margin-2x: var(--ytd-margin-2y);
  406. --ytd-margin-4x: var(--ytd-margin-4y);
  407. --ytd-margin-6x: var(--ytd-margin-6y);
  408. --ytd-margin-8x: var(--ytd-margin-8y);
  409. }
  410.  
  411. #secondary-inner.style-scope.ytd-watch-flexy {
  412. display: flex;
  413. flex-direction: column;
  414. height: 100%;
  415. }
  416.  
  417. #movie_player {
  418. position: relative;
  419. > .html5-video-container:has(video) {
  420. top: 0;
  421. bottom: 0;
  422. left: 0;
  423. right: 0;
  424. position: absolute;
  425. }
  426.  
  427. .html5-video-container > video {
  428. width: unset !important;
  429. height: 100% !important;
  430. left: 0 !important;
  431. right: 0 !important;
  432. max-height: 100%;
  433. max-width: 100%;
  434. margin: 0 auto;
  435. }
  436.  
  437. .ytp-iv-video-content {
  438. width: 100% !important;
  439. height: 100% !important;
  440. }
  441.  
  442. /*
  443. // this is buggy; eg multiple chapter hover container; can be fixed by YouTube Video Resize Fix Only
  444. .ytp-chapter-hover-container[style*="width"] {
  445. width: 100% !important;
  446. }
  447. */
  448. }
  449.  
  450. #chat:not([collapsed]) {
  451. flex: 77;
  452. }
  453.  
  454. #right-tabs {
  455. display: flex;
  456. margin: 0 !important;
  457. flex: 1;
  458. flex-direction: column;
  459.  
  460. #material-tabs,
  461. .tab-content {
  462. outline: 0;
  463. }
  464.  
  465. .tab-content {
  466. flex: 77;
  467. }
  468. }
  469.  
  470. &[is-two-columns_] #primary-inner > *:not(#player) {
  471. padding: 0 primary-content-margin 0;
  472. }
  473.  
  474. &:not([is-two-columns_]) #primary-inner > *:not(#player) {
  475. padding: 0;
  476. }
  477.  
  478. &:not([is-two-columns_]) #primary-inner #below > *:not(ytd-live-chat-frame#chat) {
  479. padding: 0 primary-content-margin 0;
  480. }
  481.  
  482. #player-container-outer.ytd-watch-flexy {
  483. max-width: unset;
  484. }
  485. }
  486.  
  487. ytd-watch-flexy.style-scope[is-two-columns_]:not([theater]):not([fullscreen]) {
  488.  
  489.  
  490. ytd-live-chat-frame#chat:not([collapsed]) {
  491. min-height: unset;
  492. }
  493. }
  494.  
  495. if min-below-area > 0 {
  496.  
  497.  
  498. ytd-watch-flexy.style-scope[is-two-columns_]:not([theater]):not([fullscreen]) {
  499.  
  500. #player #player-container-outer.ytd-watch-flexy, // layout outside
  501. #player #player-container-inner.ytd-watch-flexy, // no effect
  502. #player #player-container.ytd-watch-flexy { // layout inside
  503. max-height: calc(100vh - var(--ytd-toolbar-height, 0px) - var(--ylb-min-below-area, 0px));
  504. }
  505. }
  506.  
  507. ytd-watch-flexy.style-scope[is-two-columns_][theater]:not([fullscreen]) {
  508.  
  509. #player-theater-container.ytd-watch-flexy {
  510. max-height: calc(100vh - var(--ytd-toolbar-height, 0px) - var(--ylb-min-below-area, 0px));
  511. }
  512. }
  513. }
  514.  
  515. else {
  516.  
  517.  
  518. ytd-watch-flexy.style-scope[is-two-columns_]:not([theater]):not([fullscreen]) {
  519.  
  520. #player #player-container-outer.ytd-watch-flexy,
  521. #player #player-container-inner.ytd-watch-flexy,
  522. #player #player-container.ytd-watch-flexy {
  523. max-height: calc(100vh - var(--ytd-toolbar-height, 0px)); // for very wide screen
  524. }
  525. }
  526.  
  527. ytd-watch-flexy.style-scope[is-two-columns_][theater]:not([fullscreen]) {
  528.  
  529. #player-theater-container.ytd-watch-flexy {
  530. max-height: calc(100vh - var(--ytd-toolbar-height, 0px)); // for 4:3 video
  531. }
  532. }
  533. }
  534.  
  535.  
  536. body.lock-scrollbar[style*="overflow"][style*="hidden"]:has(ytd-watch-flexy[is-two-columns_] #columns.ytd-watch-flexy #primary-inner.ytd-watch-flexy #player #movie_player video[src]) { // note: might not be supported by FireFox due to its bug
  537. overflow-y: unset !important;
  538. }
  539.  
  540.  
  541. ytd-watch-flexy.style-scope[is-two-columns_] #columns.ytd-watch-flexy > #secondary.ytd-watch-flexy {
  542. width: side-panel-width;
  543. }
  544.  
  545. if no-round-border {
  546.  
  547. ytd-live-chat-frame[rounded-container],
  548. ytd-live-chat-frame[rounded-container] #show-hide-button.ytd-live-chat-frame ytd-toggle-button-renderer.ytd-live-chat-frame,
  549. ytd-live-chat-frame[rounded-container] iframe.ytd-live-chat-frame,
  550. ytd-live-chat-frame[rounded-container] #show-hide-button.ytd-live-chat-frame ytd-toggle-button-renderer.ytd-live-chat-frame button.yt-spec-button-shape-next,
  551. ytd-live-chat-frame[rounded-container] #show-hide-button.ytd-live-chat-frame ytd-toggle-button-renderer.ytd-live-chat-frame button.yt-spec-button-shape-next:hover {
  552. border-radius: unset;
  553. }
  554. }
  555.  
  556. if mode-for-single-col=="chat-fill-up" {
  557.  
  558. &:has(#below > #chat:not([collapsed])):not([tabview-loaded]) { // note: might not be supported by FireFox due to its bug
  559.  
  560. #primary-inner.style-scope.ytd-watch-flexy {
  561. max-height: 100vh;
  562. display: flex;
  563. flex-direction: column;
  564. }
  565.  
  566. #below.style-scope.ytd-watch-flexy {
  567. flex-shrink: 1;
  568. overflow: auto;
  569. position: relative;
  570. padding-top: 100%;
  571. }
  572.  
  573. #below.style-scope.ytd-watch-flexy > #chat.style-scope.ytd-watch-flexy:not([collapsed]) {
  574. margin: 0;
  575. min-height: unset;
  576. height: auto;
  577. position: absolute;
  578. top: 0;
  579. bottom: 0;
  580. right: 0;
  581. left: 0;
  582. top: 0;
  583. }
  584. }
  585. }
  586.  
  587. if disable-cinematics {
  588. #cinematics.ytd-watch-flexy {
  589. display: none;
  590. }
  591. }
  592. } //
  593. contentg() {
  594. if mode-for-single-col=="disabled" {
  595. &:has(ytd-watch-flexy[is-two-columns_]){
  596. contentf()
  597. }
  598. } else {
  599. contentf()
  600. }
  601. }
  602. content361()
  603. if mode-for-two-col == "expanded-panel" {
  604. html:has(ytd-live-chat-frame#chat:not([collapsed])):has(iframe#chatframe),
  605. /*
  606. html:has(ytd-engagement-panel-section-list-renderer[visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]:not([hidden])),
  607. html:has(.tab-content-cld:not(.tab-content-hidden)),
  608. */
  609. html[tabview-loaded]:has(ytd-watch-flexy[is-two-columns_]:not([fullscreen]):not([theater])) {
  610. contentg() //
  611. }
  612. } else if mode-for-two-col == "expanded-live" {
  613. html:has(ytd-live-chat-frame#chat:not([collapsed])):has(iframe#chatframe) {
  614. contentg() //
  615. }
  616. } else if mode-for-two-col == "expandable-live" {
  617. html:has(ytd-live-chat-frame#chat):has(iframe#chatframe) {
  618. contentg() //
  619. }
  620. } else if mode-for-two-col == "always" {
  621. html { //
  622. contentg() //
  623. }
  624. }
  625.  
  626. if single-col-mobile {
  627. html {
  628. --single-col-mobile-below-inside-display: none;
  629. }
  630. &:has(ytd-watch-flexy:not([is-two-columns_]):not([fullscreen])) {
  631.  
  632. if no-masthead-w==2 {
  633. contentNoMasthead()
  634. }
  635. contentSingleColMobile()
  636. }
  637. }
  638. }