@import "variables.less"; @import "util.less"; // Article Renderer // TODO(oliver): These are the old article styles. When we transition over // to the new styles we should remove these! .framework-perseus.perseus-article:not(.bibliotron-article) { .perseus-widget-container { &.widget-float-left { float: left; padding-right: 1em; max-width: 50%; width: 100%; } &.widget-float-right { float: right; padding-left: 1em; max-width: 50%; width: 100%; } } .perseus-renderer > .paragraph { margin-left: auto; margin-right: auto; max-width: 700px; } .paragraph.perseus-paragraph-full-width { margin-left: 0; margin-right: 0; max-width: none; > .paragraph { margin: 0; max-width: none; } } } // TODO(oliver): These are the new article styles. When we transition over // to the new styles we should remove the `.bibliotron-article` and delete // the above style rules. // NOTE(charlie): See below for the new, XOM Manatee beta typography styles, // which are applied to articles and exercises. .bibliotron-article.framework-perseus.perseus-article:not(.perseus-mobile) { @textColor: #21242c; .body-text() { color: @textColor; font-size: 20px; line-height: 30px; } @paragraphSpacing: 32px; .perseus-widget-container { .legacy-typography; &.widget-float-left, &.widget-float-right { max-width: 50%; padding-top: @paragraphSpacing; width: 100%; .perseus-image-caption .paragraph .paragraph { margin-bottom: 0; } } &.widget-float-left { float: left; padding-right: @paragraphSpacing; } &.widget-float-right { float: right; padding-left: @paragraphSpacing; } } .perseus-renderer > .paragraph { .body-text; margin: 0 auto; max-width: 688px; } .perseus-renderer > .paragraph .paragraph { // These are actual paragraphs .body-text; margin-bottom: @paragraphSpacing; margin-top: 0; // Inline math should have the same font-size as the surrounding text. // There is no wrapping element around .katex to indicate that it is // inline, so we rely on the "actual paragraph" check above // (a .paragraph that contains another .paragraph instead of a // .perseus-block-math). .katex { font-size: 100%; } } .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) { .body-text; } table { .body-text; margin-bottom: @paragraphSpacing; } h2 { font-family: inherit; font-size: 30px; font-weight: 700; line-height: 1.1; margin-bottom: 16px; margin-top: 48px; } h3 { font-family: inherit; font-size: 28px; font-weight: 700; line-height: 1.1; margin-bottom: 16px; margin-top: 32px; } h4, h5, h6 { font-family: inherit; font-size: 20px; font-weight: 700; line-height: 25px; margin-bottom: 16px; margin-top: 32px; } blockquote { padding: 0 32px; } .MathJax .math { color: inherit; } .perseus-image-widget { text-align: center; } .perseus-image-caption .perseus-renderer .paragraph .paragraph, .perseus-image-caption .perseus-renderer .paragraph ol, .perseus-image-caption .perseus-renderer .paragraph ul { color: #999; font-size: 14px; line-height: 19px; margin: 16px auto 42px; max-width: 455px; text-align: left; } .paragraph.perseus-paragraph-full-width { margin-bottom: @paragraphSpacing; margin-left: 0; margin-right: 0; max-width: none; > .paragraph { margin: 0; max-width: none; } } // Some images use an image widget, but some are just inlined in the // paragraph. Inlined images need legacy typography, too. .unresponsive-svg-image, .svg-image { .legacy-typography; } .perseus-block-math { margin-bottom: @paragraphSpacing; position: relative; &:before { background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); bottom: 0; content: ""; position: absolute; right: 0; top: 0; width: 30px; } } .perseus-block-math-inner { overflow-x: auto; padding-bottom: 8px; padding-right: 20px; padding-top: 8px; } // If the article starts with a heading, remove its unnecessary top margin. > .clearfix:first-child { > .perseus-renderer:first-child > .paragraph:first-child { h1, h2, h3, h4, h5, h6 { &:first-child { margin-top: 0; } } } } .perseus-renderer > .paragraph .perseus-formats-tooltip { padding: 8px 12px; .paragraph { margin-bottom: 0; // We don't _expect_ a radio in a tooltip. // We just need the specificity in order to override body text. ul:not(.perseus-widget-radio) { font-size: 15px; line-height: 1.5; margin: 0; } } } } // HACK(emily): This is a copy of a bunch of the mixins from the block of // styles down below. However, those styles are limited to mobile devices // only, so this block is for non-mobile devices. .framework-perseus:not(.perseus-article):not(.perseus-mobile) { // Mixins .text(@fontSize; @lineHeight; @color) { font-family: inherit; font-size: @fontSize; line-height: @lineHeight; color: @color; } // TODO(charlie): Pure defines XL as 1280px. However, Bibliotron and our new // article styles define XL as 1200px. Replace this once we've migrated // everything over to 1200px. @desktop-width-min: 1200px; @tablet-width-max: (@desktop-width-min - 1); .choice-text(@choiceTextSize, @choiceLineHeight) { .perseus-radio-option-content .perseus-renderer > .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray17); .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray17); } } .perseus-radio-rationale-content .perseus-renderer > .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray68); .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray68); .katex { color: @gray68; } } } } // TODO(emily): Distinguish between the different screen widths here. .choice-text(14px, 1.25); } // TODO(charlie): We're now applying the article typography styles to our // exercise content as well. We should remove the `.perseus-article` check and // merge these into `perseus.less`. However, we don't want to show them for // non-Bibliotron articles, so for now, we'll leave them here and enable them // explicitly for: (1) Bibliotron articles, and (2) all exercises. // TODO(charlie): When the XOM Manatee beta has concluded, we can remove the // namespacing and delete the above styles in full (assuming we ship the beta). .bibliotron-article.framework-perseus.perseus-article.perseus-mobile, .framework-perseus:not(.perseus-article).perseus-mobile { @baseUnit: 16px; // TODO(charlie): Pure defines XL as 1280px. However, Bibliotron and our new // article styles define XL as 1200px. Replace this once we've migrated // everything over to 1200px. @desktop-width-min: 1200px; @tablet-width-max: (@desktop-width-min - 1); // Mixins .text(@fontSize; @lineHeight; @color) { font-family: inherit; font-size: @fontSize; line-height: @lineHeight; color: @color; } .header(@fontSize; @lineHeight; @color; @paddingTopMultiplier) { font-weight: 700; padding-top: @baseUnit * @paddingTopMultiplier; .text(@fontSize, @lineHeight, @color); } // Sets the *content-width* of the paragraph to be a maximum value. // NOTE(benkomalo): the margin is typically added outside of Perseus itself // and is not accounted for in this value. .max-paragraph-width(@maxWidth) { .perseus-renderer > .paragraph { max-width: @maxWidth; } } .title(@fontSize; @lineHeight; @paddingTopMultiplier) { h1 { .header(@fontSize, @lineHeight, @gray17, @paddingTopMultiplier); } } .heading(@fontSize; @lineHeight; @paddingTopMultiplier) { h2 { .header(@fontSize, @lineHeight, @gray25, @paddingTopMultiplier); } } .sub-heading(@fontSize, @lineHeight, @paddingTopMultiplier) { // NOTE(charlie): Though we discourage the use of H4 and beyond, as of // 06/08/2016, there are 188 articles and exercises that use H4 (and // just 8 that use H5 or H6). As such, we provide style support for H4, // since it's still quite common--but we just replicate the H3 style. h3, h4 { .header(@fontSize, @lineHeight, @gray41, @paddingTopMultiplier); } } .body-text(@bodyTextSize; @bodyTextLineHeight) { .default-body-text { .text(@bodyTextSize, @bodyTextLineHeight, @gray41); } .perseus-renderer > .paragraph { .default-body-text; } .perseus-renderer > .paragraph .paragraph { .default-body-text; } .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) { .default-body-text; } .perseus-renderer > .paragraph ol { .default-body-text; } blockquote { .default-body-text; color: @gray68; } table { .default-body-text; } } .choice-text(@choiceTextSize, @choiceLineHeight) { .perseus-radio-option-content .perseus-renderer > .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray17); .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray17); } } .perseus-radio-rationale-content .perseus-renderer > .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray68); .paragraph { .text(@choiceTextSize, @choiceLineHeight, @gray68); .katex { color: @gray68; } } } } .image-caption(@smallTextSize; @smallTextLineHeight) { .perseus-image-caption .paragraph .paragraph { color: @gray68; font-size: @smallTextSize; line-height: @smallTextLineHeight; text-align: left; } // If the first element in the caption is the title (which will be // bold), darken that. Yes, this is hacky, and would ideally be done in // JS or inline styles. .perseus-image-caption.has-title .paragraph .paragraph { strong:first-child { color: @gray25; } } } .math(@blockMathTextSize; @blockMathLineHeight; @inlineMathTextSize; @inlineMathLineHeight) { .katex { font-size: @inlineMathTextSize; line-height: @inlineMathLineHeight; color: @gray17; } .perseus-block-math .katex { font-size: @blockMathTextSize; line-height: @blockMathLineHeight; } // HACK(charlie): I am ashamed. This seems to be the only way to revert // KaTeX rendered as Graphie labels to the KaTeX defaults, taken from: // https://github.com/Khan/KaTeX/blob/965b8a6164ee54212bf382108f256c6920eb7a70/static/katex.less#L18. // It's dangerous to resize labels, since they're deliberately // positioned relative to their background images. .graphie-label .katex { font-size: 1.21em; line-height: 1.2; } } .code(@codeTextSize; @codeTextLineHeight; @codeBlockHorizontalMarginMultiplier) { code { font-family: Courier; font-size: @codeTextSize; line-height: @codeTextLineHeight; color: @gray17; } pre { background-color: @gray95; border-radius: 4px; padding: @baseUnit; white-space: pre-wrap; @horizontalMargin: @baseUnit * @codeBlockHorizontalMarginMultiplier; margin: 0 @horizontalMargin; } } .blockquote(@blockQuoteBorderWidth; @blockQuotePadding) { blockquote { padding: 0 0 0 @blockQuotePadding; // TODO(charlie): This needs to have rounded corners, which is // impossible to do without drawing a custom element. border-left: @blockQuoteBorderWidth solid #d8d8d8; } } // Shared styles // Wipe out any margins set by legacy styles (e.g., in `perseus.less`), // unless paragraph is inside a blockquote. :not(blockquote) > div.paragraph { margin: 0; } // NOTE(charlie): The basic outline of rendered Perseus content consists of // a .perseus-renderer, followed by a series of .paragraph elements. Each // .paragraph in turn contains a single .paragraph element that itself // contains either raw text or a widget. We apply paragraph break styling to // those first .paragraph children. .perseus-renderer > .paragraph { margin: 0 auto; } .perseus-renderer > .paragraph:not(:first-child) { margin-top: 2 * @baseUnit; } .perseus-renderer > .paragraph > .paragraph { margin: 0; } // For articles: each section is wrapped in a div.clearfix .clearfix > .perseus-renderer { margin-bottom: 2 * @baseUnit; } .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) { margin: 0 0 0 1em; padding: 0; > li { // NOTE(charlie): This relies on the bullet at 1em being exactly // 22px wide (making for 32px, or 2 * @baseUnit of padding in // total). This could lead to inconsistencies across browsers. padding-left: 10px; margin-bottom: 1.5 * @baseUnit; } } .perseus-renderer > .paragraph ol { margin: 0; padding-left: 2 * @baseUnit; > li { list-style-type: decimal; margin-bottom: 1.5 * @baseUnit; } } // Support for nested lists .perseus-renderer > .paragraph ol, .perseus-renderer > .paragraph ul:not(.perseus-widget-radio) { ol, ul:not(.perseus-widget-radio) { padding-top: 1.5 * @baseUnit; } } // Disable the Safari tap highlight for block math, which is now tappable // via the tap-to-zoom functionality. .perseus-block-math { -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-touch-callout: none; } // TODO(benkomalo): these max-width values are referenced in // src/util/sizing-utils.js - if they're changed, change them there. // Phone styles @media (max-width: @pure-sm-max) { .max-paragraph-width(none); .title(24px, 1.2, 0); .heading(24px, 1.2, 1); .sub-heading(22px, 1.1, 0); .body-text(18px, 1.4); .choice-text(16px, 1.25); // NOTE(charlie): The values used in this responsive caption sizing // should be kept in sync with the instructions text sizing in // base-radio.jsx. .image-caption(14px, 1.3); .math(21px, 1.5, 21px, 1.2); .code(18px, 1.6, -1); .blockquote(4px, 18px); } // Tablet styles @media (min-width: @pure-md-min) and (max-width: @tablet-width-max) { .max-paragraph-width(512px); .title(30px, 1.1, 0); .heading(30px, 1.1, 2); .sub-heading(28px, 1.1, 1); .body-text(20px, 1.5); .choice-text(18px, 1.25); .image-caption(17px, 1.4); .math(30px, 1.3, 23px, 1.3); .code(23px, 1.3, 0); .blockquote(4px, 20px); } // Desktop styles @media (min-width: @desktop-width-min) { .max-paragraph-width(688px); .title(35px, 1.1, 0); .heading(35px, 1.1, 2); .sub-heading(30px, 1.1, 1); .body-text(22px, 1.4); .choice-text(20px, 1.25); .image-caption(20px, 1.4); .math(30px, 1.3, 25px, 1.2); .code(23px, 1.3, 0); .blockquote(5px, 20px); } // TODO(charlie): These are the existing Bibliotron article styles, less // anything that should be overridden by the new X-on-Mobile designs. Verify // that we still want these. @paragraphSpacing: 32px; .perseus-widget-container { .legacy-typography; &.widget-float-left, &.widget-float-right { max-width: 50%; padding-top: @paragraphSpacing; width: 100%; .perseus-image-caption .paragraph .paragraph { margin-bottom: 0; } } &.widget-float-left { float: left; padding-right: @paragraphSpacing; } &.widget-float-right { float: right; padding-left: @paragraphSpacing; } } .MathJax .math { color: inherit; } .perseus-image-widget { text-align: center; } .perseus-block-math { padding-top: @baseUnit; padding-bottom: @baseUnit; } .paragraph.perseus-paragraph-full-width { margin-left: 0; margin-right: 0; max-width: none; > .paragraph { margin: 0; max-width: none; } } // Some images use an image widget, but some are just inlined in the // paragraph. Inlined images need legacy typography, too. .unresponsive-svg-image, .svg-image { .legacy-typography; } .perseus-renderer > .paragraph .perseus-formats-tooltip { padding: 8px 12px; .paragraph { margin-bottom: 0; // We don't _expect_ a radio in a tooltip. // We just need the specificity in order to override body text. ul:not(.perseus-widget-radio) { font-size: 15px; line-height: 1.5; margin: 0; } } } } /* Derived from the MIT-licensed zoom.js: https://github.com/fat/zoom.js/blob/fd4f3e43153da7596da0bade198e99f98b47791e/ */ @zoomOverlayZIndex: 9000; @zoomAnimationDurationMs: 300ms; .zoomable { cursor: pointer; cursor: -webkit-zoom-in; cursor: -moz-zoom-in; } .zoom-img { // NOTE(charlie): We set the zoomed image's background color to white so // that any images with transparent backgrounds (like SVGs and some PNGs) // remain legible over the article content, as our backdrop is opaque. background-color: white; position: absolute; z-index: @zoomOverlayZIndex + 1; } img.zoom-img { cursor: pointer; cursor: -webkit-zoom-out; cursor: -moz-zoom-out; } .zoom-transition { -webkit-transition: transform @zoomAnimationDurationMs ease; -ms-transition: transform @zoomAnimationDurationMs ease; transition: transform @zoomAnimationDurationMs ease; } .zoom-overlay { z-index: @zoomOverlayZIndex; position: fixed; top: 0; left: 0; right: 0; bottom: 0; overflow: scroll; } .zoom-overlay-open, .zoom-overlay-transitioning { cursor: default; } // Disable vertical scrolling on the page when image is opened in modal. .zoom-overlay-open { height: 100%; max-height: 100%; overflow: hidden; } // Render an opaque backdrop upon zoom. .zoom-backdrop { z-index: @zoomOverlayZIndex - 1; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: white; opacity: 0; -webkit-transition: opacity @zoomAnimationDurationMs; -ms-transition: opacity @zoomAnimationDurationMs; transition: opacity @zoomAnimationDurationMs; } .zoom-overlay-open > .zoom-backdrop { opacity: 0.9; }