YouTube Live Borderless

Make YouTube Live Borderless

目前為 2023-01-02 提交的版本,檢視 最新版本

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