Twitter.com: un-trim images on hover

Reveal cropped portions of content while post is under mouse pointer.

  1. /* ==UserStyle==
  2. @name Twitter.com: un-trim images on hover
  3. @description Reveal cropped portions of content while post is under mouse pointer.
  4. @namespace myfonj
  5. @version 1.0.17
  6. @license CC0 - Public Domain
  7. ==/UserStyle== */
  8.  
  9. @-moz-document domain("twitter.com") {
  10. /*
  11. Twitter.com: un-trim images on hover
  12.  
  13. https://greatest.deepsurf.us/en/scripts/402913/versions/new
  14. RIP https://userstyles.org/styles/175427/edit
  15.  
  16. */
  17. /*
  18. let the spice flow. over.
  19. */
  20. div[aria-label^="Timeline: "] > div > div:hover {
  21. overflow: visible !important;
  22. z-index: 10;
  23. }
  24. div[aria-label^="Timeline: "] > div > div:hover * {
  25. overflow: visible !important;
  26. }
  27. /*
  28. directly hovered position something always above its unhovered siblings
  29. */
  30. div[aria-label^="Timeline: "] > div > div:hover *:hover {
  31. z-index: 20;
  32. }
  33. /*
  34. counters covered by box would be inaccessible, move them above and make 'em transparent ...
  35. */
  36. div[aria-label^="Timeline: "] > div > div:hover [role="group"],
  37. div[aria-label^="Timeline: "] > div > div:hover [role="link"][data-focusable="true"][href$="/media_tags"] {
  38. z-index: 30;
  39. opacity: 0;
  40. }
  41.  
  42. /* tweet actions */
  43. div[aria-label^="Timeline: "] > div > div:hover [role="group"] {
  44. outline: 20px solid rgba(0, 0, 0, 0.5);
  45. background-color: rgba(0, 0, 0, 0.5);
  46. }
  47. /*
  48. ... until hovered
  49. */
  50. div[aria-label^="Timeline: "] > div > div:hover [role="group"]:hover,
  51. div[aria-label^="Timeline: "] > div > div:hover [role="link"][data-focusable="true"][href$="/media_tags"]:hover {
  52. opacity: 1 !important;
  53. }
  54.  
  55. /*
  56. fix for external link badge text underlayed by illustration producing non-contrasting text
  57. */
  58. div[aria-label^="Timeline: "] > div > div:hover a[href^="https://t.co/"][href$="?amp=1"][target="_blank"][role="link"][data-focusable="true"][rel=" noopener noreferrer"]:hover {
  59. background-color: rgba(0, 0, 0, 0.5);
  60. }
  61. /* tweet text */
  62. div[aria-label^="Timeline: "] > div > div [style^="flex-basis"] + div [dir][lang]:hover,
  63. div[aria-label^="Timeline: "] > div > div [style^="flex-basis"]:hover + div [dir][lang] {
  64. z-index: 30;
  65. background-color: rgba(0, 0, 0, 0.5);
  66. border-left: 10px solid transparent;
  67. margin-left: -10px;
  68. }
  69. /*
  70. this is it - this *invisible* image just sits there covering div with very same image as background,
  71. "squeezed" into wrapper. so let's unleash it while invisible to gain some performace
  72. */
  73. div[aria-label^="Timeline: "] > div > div [aria-label] > img {
  74. width: auto !important;
  75. height: auto !important;
  76. max-width: calc(100vw - 20em) !important;
  77. /* too lazy to measure sidebar for now */
  78. min-width: calc(100%) !important;
  79. /* sometimes there is small pic that would otherwise downscale */
  80. outline: 3px solid black;
  81. z-index: 100 !important;
  82. }
  83. /*
  84. tadaa, real pic an all its glory. most probably bigger
  85. */
  86. div[aria-label^="Timeline: "] > div > div:hover [aria-label] > img {
  87. opacity: 1 !important;
  88. }
  89. div[aria-label^="Timeline: "] > div > div:hover [aria-label] > img:hover {
  90. box-shadow: rgba(217, 217, 217, 0.2) 0px 0px 10px, rgba(217, 217, 217, 0.25) 0px 3px 6px 3px;
  91. }
  92.  
  93. /* 2020-06 - avatars in timeline started to follow same principle, so became hover "jumpy"
  94. since we are zooming them in detail popups anyway, just be dirty and brutal for now
  95. 2021-03-11 switched to super general SRC URL matching logic
  96. */
  97. div[aria-label^="Timeline: "]:not(#\0) [style*="pbs.twimg.com/profile_images"] + img[src*="pbs.twimg.com/profile_images"],
  98. div[aria-label^="Timeline: "]:not(#\0) [style*="/default_profile_images/"] + img[src*="/default_profile_images/"] {
  99. display: none !important;
  100. outline: 1px solid red !important;
  101. }
  102.  
  103. /*
  104. Increase size of avatar pictures in hover popup
  105. this is hell to debug, so please dont't judge
  106. the popup has bottom/top according relative placement in viewport
  107. 2021-04-06 they removed [tabindex="-1"]
  108. 2021-12-13 they switched to [style*='clip-path: url("#circle-hw-shapeclip-clipconfig")'] mangledness here as well. But OTOH seems we can use way more simple selector for it
  109. */
  110. [style^="left: "][style*="px; top: "][style$="px;"] [style^="height: "][style*="px; width: "][style$="px;"] {
  111. width: 192px !important;
  112. height: 192px !important;
  113. image-rendering: crisp-edges;
  114. }
  115. /*
  116. follow / following cell (button)
  117. squeeze a bit
  118. */
  119. [style^="left: "][style*="px; top: "][style$="px;"] [style^="height: "][style*="px; width: "][style$="px;"] + div > * {
  120. padding: 0 .2em !important;
  121.  
  122. }
  123.  
  124. /*
  125. fix video player controls
  126. since it is serious mess, lets adore the emphemeral structure I had to sieve trough:
  127. */
  128. /*
  129. // for ilustration, where it begins. from here it is just classes copied from devtools
  130. (unreliable I assume) and some hand copied attributes
  131. html
  132. > body>
  133. > div#react-root
  134. > div.css-1dbjc4n.r-13awgt0.r-12vffkv
  135. > div.css-1dbjc4n.r-13awgt0.r-12vffkv
  136. > div.css-1dbjc4n.r-18u37iz.r-13qz1uu.r-417010
  137. > main.css-1dbjc4n.r-1habvwh.r-16xksha.r-1wbh5a2
  138. > div.css-1dbjc4n.r-150rngu.r-16y2uox.r-1wbh5a2.r-33ulu8
  139. > div.css-1dbjc4n.r-aqfbo4.r-16y2uox
  140. > div.css-1dbjc4n.r-1oszu61.r-1niwhzg.r-18u37iz.r-16y2uox.r-1wtj0ep.r-2llsf.r-13qz1uu
  141. > div.css-1dbjc4n.r-yfoy6g.r-18bvks7.r-1ljd8xs.r-13l2t4g.r-1phboty.r-1jgb5lz.r-11wrixw.r-61z16t.r-1ye8kvj.r-13qz1uu.r-184en5c
  142. > div.css-1dbjc4n
  143. > div.css-1dbjc4n
  144. > div.css-1dbjc4n.r-16y2uox
  145. > div.css-1dbjc4n.r-1jgb5lz.r-1ye8kvj.r-13qz1uu
  146. > div.css-1dbjc4n
  147. > section.css-1dbjc4n
  148. > div.css-1dbjc4n[aria-label^="Timeline: "]:not([REM="yup, this is the timeline"])
  149. > div[style^="position: relative; min-height: "][style$="px;"]
  150. > div[style^="position: absolute; width: 100%; transform: translateY("][style$="px); transition: opacity 0.3s ease-out 0s;"]:not([REM="THIS IS ACTUAL POST WRAPPER"])
  151. > div.css-1dbjc4n.r-1ila09b.r-qklmqi.r-1adg3ll.r-1ny4l3l
  152. > div.css-1dbjc4n
  153. > article.css-1dbjc4n.r-1loqt21.r-18u37iz.r-1ny4l3l.r-o7ynqc.r-6416eg
  154. > div.css-1dbjc4n.r-eqz5dr.r-16y2uox.r-1wbh5a2
  155. > div.css-1dbjc4n.r-16y2uox.r-1wbh5a2.r-1ny4l3l.r-1udh08x.r-1yt7n81.r-ry3cjt
  156. > div.css-1dbjc4n
  157. > div.css-1dbjc4n.r-18u37iz
  158. > div.css-1dbjc4n.r-1iusvr4.r-16y2uox.r-1777fci.r-1mi0q7o
  159. > div.css-1dbjc4n
  160. > div.css-1dbjc4n
  161. > div[class]:only-child
  162. > div[class]:only-child
  163. > div[class]:only-child
  164. > div[class]:only-child
  165. |
  166. _______________________________________________________________/
  167. / from here on just "reliable" attributes and pseudo-structure
  168. |
  169. > div[style="padding-bottom: 56.25%;"]:first-child
  170. + div:last-child
  171. > div[data-testid="placementTracking"]
  172. > div[data-testid="videoPlayer"]
  173. > div
  174. > div[style="padding-bottom: 56.25%;"]:first-child
  175. + div:last-child
  176. > div[style="height: 100%; position: relative; transform: translateZ(0px); width: 100%;"]
  177. > div[style="height: 100%; position: absolute; width: 100%;"]:not([class]):first-child
  178. > div[style="position: relative; width: 100%; height: 100%; background-color: transparent; overflow: hidden;"]
  179. > video:not([REM="OMG, here is the video"])
  180. + div:not([style]):last-child
  181. > div:not([class]):only-child
  182. > div:first-child:not([REM="this is the bugger I couldn't push under the video controls"])
  183. + div:not([class])
  184. + div:not([class])
  185. + div:not([class])
  186. > div[style="transition-duration: 250ms; transition-property: opacity, height; transition-timing-function: ease; will-change: opacity; opacity: 1;"]
  187. > div[class]
  188. > div[style="background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.77));"]
  189. > div:first-child:not([REM="this is progress / seeker wrapper"])
  190. + div:last-child:not([REM="this is video controls wrapper"])
  191. */
  192.  
  193. div[style^="padding-bottom: "][style$="%;"]:first-child
  194. + div:last-child
  195. > div[data-testid="placementTracking"]
  196. > div[data-testid="videoPlayer"]
  197. > div
  198. > div[style^="padding-bottom: "][style$="%;"]:first-child
  199. + div:last-child
  200. > div[style="height: 100%; position: relative; transform: translateZ(0px); width: 100%;"]
  201. > div[style="height: 100%; position: absolute; width: 100%;"]:not([class]):first-child
  202. + div:not([style]):last-child
  203. > div:not([class]):only-child
  204. > div:first-child:not([REM="this is the bugger I couldn't push under the video controls"])
  205. {
  206. z-index: 0;
  207. }
  208. /*
  209. [:shivers:]
  210. */
  211.  
  212. /*
  213. § dim sidebar until hovered
  214. */
  215. [data-testid="sidebarColumn"]:not(:hover) {
  216. opacity: .7
  217. }
  218.  
  219. /*
  220. § old school "inacessible" follow buttons - use primary "white on blue" instead of black on white
  221. */
  222. div[role="button"][tabindex="0"][aria-label^="Follow @"] {
  223. background-color: rgb(29, 161, 242) !important;
  224. }
  225. div[role="button"][tabindex="0"][aria-label^="Follow @"]:focus,
  226. div[role="button"][tabindex="0"][aria-label^="Follow @"]:hover {
  227. background-color: rgb(19, 141, 212) !important;
  228. }
  229. div[role="button"][tabindex="0"][aria-label^="Follow @"] * {
  230. color: #fff !important;
  231. }
  232.  
  233. div[role="button"][tabindex="0"][aria-label^="Following @"] {
  234. background-color: darkgreen !important;
  235. }
  236. div[role="button"][tabindex="0"][aria-label^="Following @"]:hover ,
  237. div[role="button"][tabindex="0"][aria-label^="Following @"]:focus {
  238. background-color: darkred !important;
  239. }
  240. div[role="button"][tabindex="0"][aria-label^="Following @"] * {
  241. color: #fff !important;
  242. }
  243.  
  244. }