mileOfSunshine / blog

2 stars 0 forks source link

Daily CSS #26

Open mileOfSunshine opened 4 years ago

mileOfSunshine commented 4 years ago

1. Reveals an interactive popout menu on hover and focus.

• position: relative on the reference parent establishes a Cartesian positioning context for its child. • position: absolute takes the popout menu out of the flow of the document and positions it in relation to the parent. • left: 100% moves the the popout menu 100% of its parent's width from the left. • visibility: hidden hides the popout menu initially and allows for transitions (unlike display: none). • .reference:hover > .popout-menu means that when .reference is hovered over, select immediate children with a class of .popout-menu and change their visibility to visible, which shows the popout. • .reference:focus > .popout-menu means that when .reference is focused, the popout would be shown. • .reference:focus-within > .popout-menu ensures that the popout is shown when the focus is within the reference.

<div class="reference" tabindex="0">
  <div class="popout-menu">Popout menu</div>
</div>

<style>
.reference {
  position: relative;
  background: tomato;
  width: 100px;
  height: 80px;
}

.popout-menu {
  position: absolute;
  visibility: hidden;
  left: 100%;
  background: #333;
  color: white;
  padding: 16px;
}

.reference:hover > .popout-menu,
.reference:focus > .popout-menu,
.reference:focus-within > .popout-menu {
  visibility: visible;
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

2. Creates an animated underline effect when the text is hovered over.

• display: inline-block makes the block p an inline-block to prevent the underline from spanning the entire parent width rather than just the content (text). • position: relative on the element establishes a Cartesian positioning context for pseudo-elements. • :after defines a pseudo-element. • position: absolute takes the pseudo element out of the flow of the document and positions it in relation to the parent. • width: 100% ensures the pseudo-element spans the entire width of the text block. • transform: scaleX(0) initially scales the pseudo element to 0 so it has no width and is not visible. • bottom: 0 and left: 0 position it to the bottom left of the block. • transition: transform 0.25s ease-out means changes to transform will be transitioned over 0.25 seconds with an ease-out timing function. • transform-origin: bottom right means the transform anchor point is positioned at the bottom right of the block. • :hover:after then uses scaleX(1) to transition the width to 100%, then changes the transform-origin to bottom left so that the anchor point is reversed, allowing it transition out in the other direction when hovered off.

<p class="hover-underline-animation">Hover this text to see the effect!</p>

<style>
.hover-underline-animation {
  display: inline-block;
  position: relative;
  color: #0087ca;
}

.hover-underline-animation:after {
  content: '';
  position: absolute;
  width: 100%;
  transform: scaleX(0);
  height: 2px;
  bottom: 0;
  left: 0;
  background-color: #0087ca;
  transform-origin: bottom right;
  transition: transform 0.25s ease-out;
}

.hover-underline-animation:hover:after {
  transform: scaleX(1);
  transform-origin: bottom left;
}
</style>

slider

点击查看效果

mileOfSunshine commented 4 years ago

3. Changes the styling of text selection.

• ::selection defines a pseudo selector on an element to style text within it when selected. Note that if you don't combine any other selector your style will be applied at document root level, to any selectable element. • Requires prefixes for full support and is not actually in any specification.

<p class="custom-text-selection">Select some of this text.</p>

<style>
::selection {
  background: aquamarine;
  color: black;
}

.custom-text-selection::selection {
  background: deeppink;
  color: white;
}
</style>

image

点击查看效果

mileOfSunshine commented 4 years ago

4.Gives text a gradient color.

• background: -webkit-linear-gradient(...) gives the text element a gradient background. • webkit-text-fill-color: transparent fills the text with a transparent color. • webkit-background-clip: text clips the background with the text, filling the text with the gradient background as the color. • Uses non-standard properties.

<p class="gradient-text">Gradient text</p>

<style>
.gradient-text {
  background: linear-gradient(#70d6ff, #00072d);
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  font-size: 32px;
}
</style>

image

点击查看效果

mileOfSunshine commented 4 years ago

Horizontally and vertically centers a child element within a parent element using grid.

• display: grid creates a grid layout • justify-content: center centers the child horizontally. • align-items: center centers the child vertically.

<div class="grid-centering">
  <div class="child">Centered content.</div>
</div>

<style>
.grid-centering {
  display: grid;
  justify-content: center;
  align-items: center;
  height: 100px;
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

Displays a hamburger menu which transitions to a cross on hover.

• Use a .hamburger-menu container div which contains the top, bottom, and middle bars. • The container is set to be a flex container (display: flex) with flex-direction to be column and flex-wrap to be wrap (alternatively, you can set both properties by a shorthand flex-flow: column wrap). • Add distance between the bars using justify-content: space-between. • The animation has 3 parts: top and bottom bars transforming to 45 degree angles (rotate(45deg)), and the middle bar fading away by setting opacity: 0. • The transform-origin is set to left so the bars rotate around the left point. • Set transition all 0.5s so that both transform and opacity properties are animated for half a second.

<div class="hamburger-menu">
  <div class="bar top"></div>
  <div class="bar middle"></div>
  <div class="bar bottom"></div>
</div>

<style>
.hamburger-menu {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: space-between;
  height: 2.5rem;
  width: 2.5rem;
  cursor: pointer;
}

.hamburger-menu .bar {
  height: 5px;
  background: black;
  border-radius: 5px;
  margin: 3px 0px;
  transform-origin: left;
  transition: all 0.5s;
}

.hamburger-menu:hover .top {
  transform: rotate(45deg);
}

.hamburger-menu:hover .middle {
  opacity: 0;
}

.hamburger-menu:hover .bottom {
  transform: rotate(-45deg);
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

Transitions an element's height from 0 to auto when its height is unknown.

• transition: max-height: 0.5s cubic-bezier(...) specifies that changes to max-height should be transitioned over 0.5 seconds, using an ease-out-quint timing function. • overflow: hidden prevents the contents of the hidden element from overflowing its container. • max-height: 0 specifies that the element has no height initially. • .target:hover > .el specifies that when the parent is hovered over, target a child .el within it and use the --max-height variable which was defined by JavaScript. • el.scrollHeight is the height of the element including overflow, which will change dynamically based on the content of the element. • el.style.setProperty(...) sets the --max-height CSS variable which is used to specify the max-height of the element the target is hovered over, allowing it to transition smoothly from 0 to auto. • Causes reflow on each animation frame, which will be laggy if there are a large number of elements beneath the element that is transitioning in height.

<div class="trigger">
  Hover me to see a height transition.
  <div class="el">Additional content</div>
</div>

<style>
.el {
  transition: max-height 0.5s;
  overflow: hidden;
  max-height: 0;
}

.trigger:hover > .el {
  max-height: var(--max-height);
}
</style>

<script>
let el = document.querySelector('.el')
let height = el.scrollHeight
el.style.setProperty('--max-height', height + 'px')
</script>

点击查看效果

mileOfSunshine commented 4 years ago

Creates a rotate effect for the image on hover.

• Use scale and rotate when hovering over the parent element (a figure) to animate the image, using the transition property. • Use overflow: hidden on the parent container to hide the excess from the image transformation.

<figure class="hover-rotate">
  <img src="http://t8.baidu.com/it/u=1484500186,1503043093&fm=79&app=86&size=h300&n=0&g=4n&f=jpeg?sec=1594120746&t=a5b84c6c36d1562dfad2a6a15a6b791b" />
</figure>

<style>
.hover-rotate {
  overflow: hidden;
  margin: 8px;
  min-width: 240px;
  max-width: 320px;
  width: 100%;
}

.hover-rotate img {
  transition: all 0.3s;
  box-sizing: border-box;
  max-width: 100%;
}

.hover-rotate:hover img {
  transform: scale(1.3) rotate(5deg);
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

Creates a vertical masonry layout using HTML and CSS.

• Create a masonry-style layout that consists of "bricks" that fall into each other with either a fixed width (vertical layout) or a fixed height (horizontal layout), forming a perfect fit. Especially useful when working with images. • .masonry-container is the container for the masonry layout. Within that container, there's a div.masonry-columns, which will automatically put each child element, .masonry-brick, into the layout. • .masonry-brick must be have display: block to allow the layout to flow properly, while the :first-child of this class should have a different margin to account for its positioning. • CSS variables are used to allow for greater flexibility for the layout, while media queries ensure that the layout flows responsively in different viewport sizes.

<div class="masonry-container">
  <div class="masonry-columns">
    <img class="masonry-brick" src="https://picsum.photos/id/1016/384/256" alt="An image" />
    <img class="masonry-brick" src="https://picsum.photos/id/1025/495/330" alt="Another image" />
    <img class="masonry-brick" src="https://picsum.photos/id/1024/192/128" alt="Another image" />
    <img class="masonry-brick" src="https://picsum.photos/id/1028/518/345" alt="One more image" />
    <img class="masonry-brick" src="https://picsum.photos/id/1035/585/390" alt="And another one" />
    <img class="masonry-brick" src="https://picsum.photos/id/1074/384/216" alt="Last one" />
  </div>
</div>

<style>
/* Container */
.masonry-container {
  --column-count-small: 1;
  --column-count-medium: 2;
  --column-count-large: 3;
  --column-gap: 0.125rem;
  padding: var(--column-gap);
}

/* Columns */
.masonry-columns {
  column-gap: var(--column-gap);
  column-count: var(--column-count-small);
  column-width: calc(1 / var(--column-count-small) * 100%);
}

@media only screen and (min-width: 640px) {
  .masonry-columns {
    column-count: var(--column-count-medium);
    column-width: calc(1 / var(--column-count-medium) * 100%);
  }
}

@media only screen and (min-width: 800px) {
  .masonry-columns {
    column-count: var(--column-count-large);
    column-width: calc(1 / var(--column-count-large) * 100%);
  }
}

/* Bricks */
.masonry-brick {
  width: 100%;
  height: auto;
  margin: var(--column-gap) 0;
  display: block;
}

.masonry-brick:first-child {
  margin: 0 0 var(--column-gap);
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

A hover effect where the gradient follows the mouse cursor.

• --x and --y are used to track the position of the mouse on the button. • --size is used to keep modify of the gradient's dimensions. • background: radial-gradient(circle closest-side, pink, transparent); creates the gradient at the correct postion.

<button class="mouse-cursor-gradient-tracking">
  <span>Hover me</span>
</button>

<style>
.mouse-cursor-gradient-tracking {
  position: relative;
  background: #7983ff;
  padding: 0.5rem 1rem;
  font-size: 1.2rem;
  border: none;
  color: white;
  cursor: pointer;
  outline: none;
  overflow: hidden;
}

.mouse-cursor-gradient-tracking span {
  position: relative;
}

.mouse-cursor-gradient-tracking:before {
  --size: 0;
  content: '';
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--size);
  height: var(--size);
  background: radial-gradient(circle closest-side, pink, transparent);
  transform: translate(-50%, -50%);
  transition: width 0.2s ease, height 0.2s ease;
}

.mouse-cursor-gradient-tracking:hover:before {
  --size: 200px;
}
</style>

<style>
let btn = document.querySelector('.mouse-cursor-gradient-tracking')
btn.onmousemove = function(e) {
  let rect = e.target.getBoundingClientRect()
  let x = e.clientX - rect.left
  let y = e.clientY - rect.top
  btn.style.setProperty('--x', x + 'px')
  btn.style.setProperty('--y', y + 'px')
}
</style>

点击查看效果

mileOfSunshine commented 4 years ago

Adds a fading gradient to an overflowing element to better indicate there is more content to be scrolled.

• position: relative on the parent establishes a Cartesian positioning context for pseudo-elements. • :after defines a pseudo element. • background-image: linear-gradient(...) adds a linear gradient that fades from transparent to white (top to bottom). • position: absolute takes the pseudo element out of the flow of the document and positions it in relation to the parent. • width: 240px matches the size of the scrolling element (which is a child of the parent that has the pseudo element). • height: 25px is the height of the fading gradient pseudo-element, which should be kept relatively small. • bottom: 0 positions the pseudo-element at the bottom of the parent. • pointer-events: none specifies that the pseudo-element cannot be a target of mouse events, allowing text behind it to still be selectable/interactive.

<div class="overflow-scroll-gradient">
  <div class="overflow-scroll-gradient-scroller">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. <br />
    Iure id exercitationem nulla qui repellat laborum vitae, <br />
    molestias tempora velit natus. Quas, assumenda nisi. <br />
    Quisquam enim qui iure, consequatur velit sit? <br />
    Lorem ipsum dolor sit amet consectetur adipisicing elit.<br />
    Iure id exercitationem nulla qui repellat laborum vitae, <br />
    molestias tempora velit natus. Quas, assumenda nisi. <br />
    Quisquam enim qui iure, consequatur velit sit?
  </div>
</div>

<style>
.overflow-scroll-gradient {
  position: relative;
}

.overflow-scroll-gradient:after {
  content: '';
  position: absolute;
  bottom: 0;
  width: 250px;
  height: 25px;
  background: linear-gradient(transparent, white);
  pointer-events: none;
}

.overflow-scroll-gradient-scroller {
  overflow-y: scroll;
  background: white;
  width: 240px;
  height: 200px;
  padding: 15px;
  line-height: 1.2;
}
</style>

效果

mileOfSunshine commented 4 years ago

A nicer alternative to text-decoration: underline where descenders do not clip the underline.

Natively implemented as text-decoration-skip-ink: auto but it has less control over the underline. • text-shadow uses 4 values with offsets that cover a 4x4 px area to ensure the underline has a "thick" shadow that covers the line where descenders clip it. Use a color that matches the background. For a larger font, use a larger px size. Additional values can create an even thicker shadow, and subpixel values can also be used. • background-image: linear-gradient(...) creates a 90deg gradient using the text color (currentColor). • The background-* properties size the gradient as 100% of the width of the block and 1px in height at the bottom and disables repetition, which creates a 1px underline beneath the text. • The ::selection pseudo selector rule ensures the text shadow does not interfere with text selection.

<p class="pretty-text-underline">Pretty text underline without clipping descenders.</p>

<style>
.pretty-text-underline {
  display: inline;
  text-shadow: 1px 1px #f5f6f9, -1px 1px #f5f6f9, -1px -1px #f5f6f9, 1px -1px #f5f6f9;
  background-image: linear-gradient(90deg, currentColor 100%, transparent 100%);
  background-position: bottom;
  background-repeat: no-repeat;
  background-size: 100% 1px;
}

.pretty-text-underline::-moz-selection {
  background-color: rgba(0, 150, 255, 0.3);
  text-shadow: none;
}

.pretty-text-underline::selection {
  background-color: rgba(0, 150, 255, 0.3);
  text-shadow: none;
}
</style>

效果

mileOfSunshine commented 4 years ago

Creates a pulse effect loader animation using the animation-delay property.

• Use @keyframes to define an animation at two points in the cycle, start (0%), where the two <div> elements have no width or height and are positioned at the center and end (100%), where both <div> elements have increased width and height, but their position is reset to 0. • Use opacity to transition from 1 to 0 when animating to give the <div>elements a disappearing effect as they expand. • .ripple-loader, which is the parent container, has a predefined width and height. It uses position: relative to position its children. • Use animation-delay on the second <div> element, so that each element starts its animation at a different time.

<div class="ripple-loader">
  <div></div>
  <div></div>
</div>

<style>
.ripple-loader {
  position: relative;
  width: 64px;
  height: 64px;
}

.ripple-loader div {
  position: absolute;
  border: 4px solid #454ade;
  border-radius: 50%;
  animation: ripple-loader 1s ease-out infinite;
}

.ripple-loader div:nth-child(2) {
  animation-delay: -0.5s;
}

@keyframes ripple-loader {
  0% {
    top: 32px;
    left: 32px;
    width: 0;
    height: 0;
    opacity: 1;
  }
  100% {
    top: 0;
    left: 0;
    width: 64px;
    height: 64px;
    opacity: 0;
  }
}
</style>

效果

mileOfSunshine commented 4 years ago

Resets all styles to default values with one property. This will not affect direction and unicode-bidi properties.

• The all property allows you to reset all styles (inherited or not) to default values.

<div class="reset-all-styles">
  <h5>Title</h5>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure id exercitationem nulla qui repellat laborum vitae, molestias tempora velit natus.
    Quas, assumenda nisi. Quisquam enim qui iure, consequatur velit sit?
  </p>
</div>

<style>
.reset-all-styles {
  all: initial;
}
</style>

效果

mileOfSunshine commented 4 years ago

Creates a donut spinner that can be used to indicate the loading of content.

• Use a semi-transparent border for the whole element, except one side that will serve as the loading indicator for the donut. Use animation to rotate the element.

<div class="donut"></div>

<style>
@keyframes donut-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.donut {
  display: inline-block;
  border: 4px solid rgba(0, 0, 0, 0.1);
  border-left-color: #7983ff;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  animation: donut-spin 1.2s linear infinite;
}
</style>

效果