.rendered_markdown { /* The default top/bottom margins for paragraphs are small, to make sure they look nice next to blockquotes, lists, etc. */ & p { margin: 3px 0; } /* The spacing between two paragraphs is significantly larger. We arrange things so that this spacing matches the spacing between paragraphs in two consecutive 1-line messages. */ & p + p { margin-top: 10px; } /* Ensure bulleted lists are nicely centered in 1-line messages */ & ul { margin: 2px 0 5px 20px; } /* Swap the left and right margins of bullets for Right-To-Left languages */ &.rtl ul { margin-right: 20px; margin-left: 0; } /* Ensure ordered lists are nicely centered in 1-line messages */ & ol { margin: 2px 0 5px 20px; } /* Swap the left and right margins of ordered list for Right-To-Left languages */ &.rtl ol { margin-right: 8px; margin-left: 0; } /* Reduce top-margin when a paragraph is followed by an ordered or bulleted list */ & p + ul, p + ol { margin-top: 0; } & hr { border-bottom: 1px solid hsl(0deg 0% 87%); border-top: 1px solid hsl(0deg 0% 87%); } /* Headings */ & h1, h2, h3, h4, h5, h6 { font-weight: 600; line-height: 1.4; margin-top: 15px; margin-bottom: 5px; } /* Headings: Ensure that messages that start with a heading don't have a weirdly blank area at the very start of the message. */ & h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { margin-top: 0; } /* We use a modest progression of heading sizes to make them stand out from normal next but avoid taking up too much space. */ & h1 { font-size: 1.4em; } & h2 { font-size: 1.3em; } & h3 { font-size: 1.2em; } & h4 { font-size: 1.1em; } & h5 { font-size: 1.05em; } & h6 { font-size: 1em; } /* Formatting for blockquotes */ & blockquote { padding-left: 5px; margin: 5px 0 6px 10px; border-left: 5px solid hsl(0deg 0% 87%); & p { line-height: inherit; font-size: inherit; } } &.rtl blockquote { padding-left: unset; padding-right: 5px; margin-left: unset; margin-right: 10px; border-left: unset; border-right: 5px solid hsl(0deg 0% 87%); } /* Formatting for Markdown tables */ & table { padding-right: 10px; margin: 5px; width: 99%; display: block; max-width: fit-content; overflow-x: auto; white-space: nowrap; border-collapse: collapse; } & thead { background-color: hsl(0deg 0% 93%); } & tr { display: table-row; vertical-align: inherit; } & tr th { border: 1px solid hsl(0deg 0% 80%); padding: 4px; text-align: left; } & tr td { border: 1px solid hsl(0deg 0% 80%); padding: 4px; } /* Emoji; sized to be easily understood while not overwhelming text. */ .emoji { height: calc(20em / 14); width: calc(20em / 14); /* "Eyeballed" styles to compensate for inline-block emoji positioning in messages. By coordinating the emoji height and width above with the `line-height` on messages in the future, these properties should no longer be necessary: */ position: relative; margin-top: -7px; top: 3px; } /* Mentions and alert words */ .user-mention-me :not(.silent) { background-color: hsl(112deg 88% 87%); } .user-group-mention, .user-mention, .topic-mention { font-size: 14px; line-height: 17px; padding: 0 3px; border-radius: 3px; white-space: nowrap; display: inline-block; } .user-mention { color: var(--color-text-other-mention); background-color: var(--color-background-text-direct-mention); &.user-mention-me { color: var(--color-text-self-direct-mention); font-weight: 600; } &:hover { background-color: var(--color-background-text-hover-direct-mention); } } .user-mention[data-user-id="*"], .user-group-mention, .topic-mention { color: var(--color-text-other-mention); background-color: var(--color-background-text-group-mention); &.user-mention-me { color: var(--color-text-self-group-mention); font-weight: 600; } } .user-group-mention { &:hover { background-color: var(--color-background-text-hover-group-mention); } } .alert-word { background-color: var(--color-background-alert-word); } /* Timestamps */ & time { background: hsl(0deg 0% 93%); border-radius: 3px; padding: 0 0.2em; box-shadow: 0 0 0 1px hsl(0deg 0% 80%); white-space: nowrap; margin-left: 2px; margin-right: 2px; display: inline-block; margin-bottom: 1px; } /* LaTeX styling */ .katex-display { /* KaTeX sometimes overdraws its bounding box by a little, so we enlarge its scrolling area by stealing 3px from the margin of the enclosing

. */ margin: -3px 0; padding: 3px 0; overflow: auto hidden; } .tex-error { color: hsl(0deg 0% 50%); } /* Spoiler styling */ .spoiler-block { border: hsl(0deg 0% 50%) 1px solid; padding: 2px 8px 2px 10px; border-radius: 10px; position: relative; top: 1px; display: block; margin: 5px 0 15px; .spoiler-header { padding: 5px; font-weight: bold; } .spoiler-content { overflow: hidden; border-top: hsl(0deg 0% 50%) 0 solid; transition: height 0.4s ease-in-out, border-top 0.4s step-end, padding 0.4s step-end; padding: 0; height: 0; &.spoiler-content-open { border-top: hsl(0deg 0% 50%) 1px solid; transition: height 0.4s ease-in-out, border-top 0.4s step-start, padding 0.4s step-start; padding: 5px; height: auto; } } .spoiler-button { float: right; width: 25px; height: 25px; &:hover .spoiler-arrow { &::before, &::after { background-color: hsl(0deg 0% 50%); } } } .spoiler-arrow { float: right; width: 13px; height: 13px; position: relative; bottom: -5px; left: -10px; cursor: pointer; transition: 0.4s ease; margin-top: 2px; text-align: left; transform: rotate(45deg); &::before, &::after { position: absolute; content: ""; display: inline-block; width: 12px; height: 3px; background-color: hsl(0deg 0% 83%); transition: 0.4s ease; } &::after { position: absolute; transform: rotate(90deg); top: -5px; left: 5px; } &.spoiler-button-open { transform: rotate(45deg) translate(-5px, -5px); &::before { transform: translate(10px, 0); } &::after { transform: rotate(90deg) translate(10px, 0); } } } } /* embedded link previews */ .message_inline_image_title { font-weight: bold; } .twitter-image, .message_inline_image { position: relative; margin-bottom: 5px; margin-right: 5px; /* Sizing CSS for inline images requires care, because images load asynchronously, and browsers will unfortunately jump your scroll position when elements load above the current position in the message feed in a way that changes the height of elements. (As of March 2022, both Firefox and Chrome exhibit this problem, though in Chrome it is pretty subtle). We prevent this by setting a fixed height for inline previews. 100px is chosen because we don't want images to overwhelm conversation in message feeds, as it does in chat tools that show images at half-screen height or larger. If there are several images next to each other, we display them in a grid format; the same considerations requires that either use a scrollable region or set a fixed width for images so that the browser statically knows whether it'll need to overflow. We choose fixed width here. */ height: 100px; width: 150px; /* Inline image containers also need an inline-block display in order to implement the desired grid layout. */ display: inline-block; /* Set a background for the image; the background will be visible for messages whose aspect ratio is different from that of this container. */ border: solid 1px transparent; transition: background 0.3s ease; background: hsl(0deg 0% 0% / 3%); &:hover { background: hsl(0deg 0% 0% / 15%); } & a { display: block; height: 100%; width: 100%; } } &.rtl .twitter-image, &.rtl .message_inline_image { margin-left: unset; margin-right: 5px; } /* In browsers that support `:has()`, we pull `.rendered_markdown` out of the baseline group formed with EDITED/MOVED markers and the timestamp when the first child of the rendered markdown is a media element. */ &:has(> .message_inline_image:first-child) { align-self: center; } /* But for browsers that don't support :has(), we provide a small layout hack using an inline grid. */ @supports not selector(:has(*)) { .message_inline_image { /* We'll display this bit of media as an inline grid. That will allow us to put beneath the image a piece of invisible ::before content that we'll generate to participate in the messagebox-content grid's baseline group. */ display: inline-grid; /* We create a grid area called "media", so that both the inner element and the ::before content can sit there. `auto` will take on the height and width otherwise assigned to the .message_inline_image. Setting the min value to 0 on minmax() ensures that media larger than those dimensions don't cause a grid blowout. */ grid-template: "media" minmax(0, auto) / minmax(0, auto); } .message_inline_image a, .message_inline_image video { /* We explicitly place the containing media element in the thumbnail area. */ grid-area: media; } .message_inline_image::before { /* We generate a single . here to create text content enough for a baseline. Generated content is not generally read aloud to screen readers. */ content: "."; /* We color the generated . transparently, so it won't be visible when the media doesn't cover the entire area. */ color: transparent; /* And we explicitly place the . in the thumbnail area, too. Otherwise, grid would generate a new column track for it to sit in. */ grid-area: media; } } .twitter-tweet { border: 1px solid hsl(0deg 0% 87%); padding: 0.5em 0.75em; margin-bottom: 0.25em; word-break: break-word; min-height: 48px; } .twitter-avatar { float: left; width: 48px; height: 48px; margin-right: 0.75em; } .message_inline_ref { margin-bottom: 5px; margin-left: 5px; height: 50px; display: block !important; border: none !important; } &.rtl .message_inline_ref { margin-left: unset; margin-right: 5px; } .twitter-image img, .message_inline_image img, .message_inline_ref img { /* We use `scale-down` so that images smaller than the container are neither scaled up up or cropped to fit. This preserves their aspect ratio, which is often helpful. */ object-fit: scale-down; /* We need to explicitly specify the image dimensions to have object-fit work; likely because internally object-fit needs to know the frame it is targeting, and images don't default to container dimensions. */ height: 100%; width: 100%; float: left; margin-right: 10px; border-radius: inherit; } .message_inline_image img { cursor: zoom-in; } .youtube-video img, .vimeo-video img, .embed-video img { cursor: pointer; } &.rtl .twitter-image img, &.rtl .message_inline_image img, &.rtl .message_inline_ref img { float: right; margin-right: unset; margin-left: 10px; } & li .message_inline_image img { float: none; } .message_inline_video { &:hover { &::after { transform: scale(1); transition: transform 0.2s; } } &::after { content: ""; background-image: url("../images/play_button.svg"); display: block; width: 32px; height: 32px; position: absolute; /* video width (100px) / 2 - icon width (32px) / 2 */ top: 34px; /* video height (150px) / 2 - icon height (32px) / 2 */ left: 59px; border-radius: 100%; transform: scale(0.8); } & video { display: block; object-fit: contain; height: 100%; width: 100%; } } .youtube-video .fa-play::before, .embed-video .fa-play::before { position: absolute; margin: var(--margin-top, 32px) 0 0 var(--margin-left, 45px); padding: 5px 8px 5px 10px; font-size: 12px; border-radius: 4px; background-color: hsl(0deg 0% 0%); color: hsl(0deg 0% 100%); opacity: 0.7; top: 0; left: 0; } .message_embed { display: block; position: relative; margin: 5px 0; border: none; border-left: 3px solid hsl(0deg 0% 93%); height: 80px; padding: 5px; z-index: 1; text-shadow: hsl(0deg 0% 0% / 1%) 0 0 1px; .message_embed_title { padding-top: 0; /* to remove the spacing that the font has from the top of the container. */ margin-top: -5px; font-size: 1.2em; line-height: normal; } .message_embed_description { position: relative; max-width: 500px; margin-top: 3px; /* to put it below the container gradient. */ z-index: -1; } .message_embed_image { display: inline-block; width: 70px; height: 70px; background-size: cover; background-position: center; } .data-container { position: relative; padding: 0 5px; display: inline-block; vertical-align: top; max-width: calc(100% - 115px); max-height: 80px; overflow: hidden; } .data-container div { display: block; border: none; } .data-container::after { content: " "; position: absolute; width: 100%; height: 10%; bottom: 0; background: linear-gradient( 0deg, hsl(0deg 0% 100%), transparent 100% ); } } &.rtl .message_embed { border-left: unset; border-right: 3px solid hsl(0deg 0% 93%); } .message_embed > * { display: inherit; padding: 5px; border: none; } & a { color: var(--color-markdown-link); text-decoration: none; & code { color: var(--color-markdown-code-link); } &:hover, &:focus { color: var(--color-markdown-link-hover); text-decoration: underline; & code { color: var(--color-markdown-code-link-hover); } } } & pre { direction: ltr; /* code block text is a bit smaller than normal text */ font-size: 0.825em; line-height: 1.4; white-space: pre; overflow-x: auto; word-break: break-all; word-wrap: normal; margin: 5px 0; padding: 5px 7px 3px; display: block; border-radius: 4px; &:hover .copy_codeblock, &:hover .code_external_link { visibility: visible; } } & pre code { font-size: inherit; padding: 0; white-space: inherit; overflow-x: scroll; /* Unset to avoid compounding alpha values */ background-color: unset; color: inherit; border: 0; } & code { /* 11.55px when body is the default 14px; this is chosen to be slightly above the 11.5px threshold where the height jumps by a pixel on most platforms. */ font-size: 0.825em; unicode-bidi: embed; direction: ltr; white-space: pre-wrap; padding: 1px 2px; color: var(--color-markdown-code-text); background-color: var(--color-markdown-code-background); border-radius: 3px; } /* Style copy-to-clipboard button inside code blocks */ .copy_codeblock { visibility: hidden; /* Having absolute positioning here ensures that the element doesn't scroll along with the code div in narrow windows */ position: absolute; right: 2px; margin-top: -4px; /* Remove the outline when clicking on the copy-to-clipboard button */ &:focus { outline: none; } } .code_external_link { visibility: hidden; position: absolute; right: 23px; margin-top: -3px; font-size: 17px; /* The default icon and on-hover colors are inherited from tag. so we set our own to match the copy-to-clipbord icon */ color: hsl(0deg 0% 47%); &:hover { color: hsl(200deg 100% 40%); } } } .group_mention, .direct_mention { & .rendered_markdown pre { background-color: var(--color-markdown-pre-background-mentions); border-color: var(--color-markdown-pre-border-mentions); } & .rendered_markdown code { background-color: var(--color-markdown-code-background-mentions); } & .rendered_markdown pre code { background-color: unset; border-color: unset; } } .preview_content .copy_codeblock { /* We avoid displaying copy_codeblock button in previews, because it feels odd given that you can just copy-paste the code out of the "edit" state. We may change this decision when we add menu options for viewing the code in a coding playground. */ display: none; } .informational-overlays .copy_codeblock { display: none; } .message_edit_history_content .copy_codeblock { /* Copy code block button is hidden in edit history, this is done because of issues faced in copying code blocks in edit history modal. This may be changed later as we decide upon a proper ux for displaying edit-history. */ display: none; } .message_edit_history_content .code_external_link { right: 5px; } .preview_content .code_external_link { right: 12px; } @media (width < $sm_min) { .rendered_markdown .message_embed { height: auto; .message_embed_image { width: 100%; height: 100px; } .data-container { display: block; max-width: 100%; margin-top: 10px; } } } .preview_content.rendered_markdown { /* Ensure that the first child and last child don't have blank area at the top and bottom respectively. */ & > :first-child { margin-top: 0; } & > :last-child { margin-bottom: 0; } } .codehilite { display: block !important; border: none !important; background: none !important; & pre { color: var(--color-markdown-pre-text); /* This is necessary to remove the background color set by Pygments. */ background-color: var(--color-markdown-pre-background); border: 1px solid var(--color-markdown-pre-border); } } /* Both the horizontal scrollbar in

 as well as
   vertical scrollbar in the