Вбудовані стилі CSS в React: як реалізувати a: наведення курсора?


178

Мені дуже подобається вбудований CSS-шаблон в React і вирішив його використовувати.

Однак ви не можете використовувати :hoverселектори та подібні. Отже, який найкращий спосіб реалізувати підсвічування під час використання вбудованих стилів CSS?

Одне з пропозицій від #reactjs - мати Clickableкомпонент і використовувати його так:

<Clickable>
    <Link />
</Clickable>

Стан Clickableмає hoveredстан і передає його як реквізит Посилання. Однак, Clickable(як я реалізував її) обгортання Linkв divтакий спосіб , щоб його можна встановити onMouseEnterі onMouseLeaveна нього. Це робить речі дещо складнішими (наприклад, spanзагорнутий у divповедінку по-іншому ніж span).

Чи є простіший спосіб?


1
Ви абсолютно праві - єдиний спосіб імітувати: набір курсорів і т. Д. Із стилями вбудованих файлів - це використання onMouseEnterта onMouseLeave. Що стосується точного втілення цього - то саме від вас залежить. Щоб переглянути ваш конкретний приклад, чому б не зробити <Clickable/>обгортку a span?
Кріс Хауфтон

3
Я б запропонував використовувати зовнішні таблиці стилів разом із плагіном ExtractText Webpack, це допоможе вам у тривалішому запуску, якщо ви хочете коли-небудь захопити ServerRender, інакше ви можете спробувати Radium github.com/FormidableLabs/radium
abhirathore2006

В даний час стильовий компонент є найкращим рішенням для моделювання всіх можливостей css / scss в реакції.
Ахмад Бехзаді

Відповіді:


43

Я в тій же ситуації. Дійсно подобається схема збереження стилю в компонентах, але наведення стану здається, як остання перешкода.

Що я зробив, це писати міксин, який ви можете додати до свого компонента, який потребує стану наведення. Цей міксин додасть нового hoveredвластивості стану вашого компонента. Буде встановлено, trueякщо користувач наводить курсор на головний вузол DOM компонента і повертає його назад, falseякщо користувачі залишають елемент.

Тепер у своїй функції відображення компонентів ви можете зробити щось на кшталт:

<button style={m(
     this.styles.container,
     this.state.hovered && this.styles.hover,
)}>{this.props.children}</button>

Тепер кожного разу, коли стан hoveredдержави змінюється, компонент буде повторно відображатися.

Я також створив для цього пісочне репо, яке використовую для тестування деяких із цих шаблонів. Перевірте це, чи хочете ви побачити приклад моєї реалізації.

https://github.com/Sitebase/cssinjs/tree/feature-interaction-mixin


3
не гарне рішення для тривалішого запуску, Radium стане кращим вибором або за допомогою зовнішньої таблиці стилів
abhirathore2006

16
@ abhirathore2006 Radium працює так само, і питання конкретно, як це зробити без використання зовнішнього аркуша стилів
Charlie Martin

Чи не було б більше сенсу використовувати оператор розкидання ванілі?
PAT-O-

102

Я думаю, що onMouseEnter та onMouseLeave - це шляхи, але я не бачу потреби в додатковому компоненті обгортки. Ось як я це реалізував:

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={linkStyle} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
}

Потім ви можете використовувати стан наведення (істинне / хибне), щоб змінити стиль посилання.


1
Здається, це прикриває, :hoverале ні:focus
Адам Таттл

3
@AdamTuttle reagi має onFocusподію; так що ви могли б зробити те ж саме для , :focusяк :hover, за винятком того, замість того , onMouseEnterі onMouseLeaveвам потрібно буде тількиonFocus
Jonathan

7
Майте на увазі, що цей метод змушує виконувати основні потоки, тоді як типові події CSS обробляються набагато ефективніше.
Hampus Ahlgren

54

Пізно до вечірки, але приходьте до рішення. Ви можете використовувати "&" для визначення стилів для наведення nth Child тощо:

day: {
    display: "flex",
    flex: "1",
    justifyContent: "center",
    alignItems: "center",
    width: "50px",
    height: "50px",
    transition: "all 0.2s",
    borderLeft: "solid 1px #cccccc",

    "&:hover": {
      background: "#efefef"
    },
    "&:last-child": {
      borderRight: "solid 1px #cccccc"
    }
},

1
Це не рішення, питання полягало у тому, як це зробити з INLINE css, а не з окремим таблицею стилів.
Еммі

35
Чувак, придивіться ближче. Це стиль IN-inline.
Ярослав Власло

15
Це не працює з React. Вам потрібна додаткова бібліотека, як стильові компоненти.
Г.Г.

3
Це не працює з вбудованим стилем, цей приклад викликає плутанину. Якщо це дійсно працює, будь ласка, надайте кращий приклад з повноцінним компонентом.
Олександр

2
Відмінно! Працює як шарм!
Федір

26

Ви можете використовувати Radium - це інструмент з відкритим кодом для стилів вбудованих стилів з ReactJS. Він додає саме потрібні вам селектори. Дуже популярний, перевірте це - Радій на npm


Я щойно натрапив на цю посаду, як би ви реалізували Radium у наступній ситуації? module.exports = React.createClass({ displayName: 'App',})

1
@Rkhayat Ви можете або обернути його як module.exports = Radium(React.createClass({ displayName: 'App',}))або призначити класу значення та додати @Radiumдекоратор над ним, як документи згадують github.com/FormidableLabs/radium#usage
pbojinov

є також ця чудова річ під назвою CSS;)
Pixelomo

11

Повна підтримка CSS - це саме причина цієї величезної кількості бібліотек CSSinJS, щоб зробити це ефективно, вам потрібно генерувати фактичні CSS, а не вбудовані стилі. Також стилі вбудованого типу набагато повільніше реагують у більшій системі. Відмова - я підтримую JSS .


9

Здійснено стиль Style - частково - з цієї причини (інші - це незгоди з реалізацією інших libs / синтаксису та вбудованих стилів (відсутність підтримки для префіксації значень властивостей)). Повірте, ми повинні мати можливість просто писати CSS в JavaScript і мати повністю автономні компоненти HTML-CSS-JS. З рядками шаблонів ES5 / ES6 ми зараз можемо, і це теж може бути досить! :)

npm install style-it --save

Функціональний синтаксис ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

Синтаксис JSX ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}

        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}

export default Intro;

Я помітив на прикладі синтаксису JSX, у посиланні JSFiddle є правильний код, але в наведеному прикладі відсутня дужка, що закривається після тега стилю закриття, і відступ вимкнено, ймовірно, через відсутні дужки.
bradleygsmith

8

Додавши до відповіді Джонатана , ось події для висвітлення фокусу та активних станів, а використання onMouseOverзамість того, onMouseEnterщо останні не будуть міхурити, якщо у вас є будь-які дочірні елементи в межах цілі, до якої застосовується подія.

var Link = React.createClass({

  getInitialState: function(){
    return {hover: false, active: false, focus: false}
  },

  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },

  toggleActive: function(){
    this.setState({active: !this.state.active})
  },

  toggleFocus: function(){
    this.setState({focus: !this.state.focus})
  },

  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else if (this.state.active) {
      linkStyle = {backgroundColor: 'blue'}
    } else if (this.state.focus) {
      linkStyle = {backgroundColor: 'purple'}
    } 

    return(
      <div>
        <a style={linkStyle} 
          onMouseOver={this.toggleHover} 
          onMouseOut={this.toggleHover} 
          onMouseUp={this.toggleActive} 
          onMouseDown={this.toggleActive} 
          onFocus={this.toggleFocus}> 
          Link 
        </a>
      </div>
    )
  }

7

Ось моє рішення за допомогою React Hooks. Він поєднує оператор розповсюдження та потрійний оператор.

style.js

export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Button.js

import React, {useState} from 'react';
import style from './style.js'

function Button(){

  const [hover, setHover] = useState(false);

  return(
    <button
      onMouseEnter={()=>{
        setHover(true);
      }}
      onMouseLeave={()=>{
        setHover(false);
      }}
      style={{
        ...style.normal,
        ...(hover ? style.hover : null)
      }}>

        MyButtonText

    </button>
  )
}


6

Це може бути хорошим хаком для того, щоб мати стиль вбудованого тексту в реагуючому компоненті (а також використовувати: навести курсор CSS-функції):

...

<style>
  {`.galleryThumbnail.selected:hover{outline:2px solid #00c6af}`}
</style>

...

5

Оформити замовлення Typestyle якщо ви використовуєте React with Typescript.

Нижче наведено зразок коду для: наведення курсора

import {style} from "typestyle";

/** convert a style object to a CSS class name */
const niceColors = style({
  transition: 'color .2s',
  color: 'blue',
  $nest: {
    '&:hover': {
      color: 'red'
    }
  }
});

<h1 className={niceColors}>Hello world</h1>

4

Ви можете використовувати модулі css як альтернативу та додатково react-css-модулі для відображення імен класів.

Таким чином ви можете імпортувати свої стилі наступним чином і використовувати звичайний css-код, локально встановлений для своїх компонентів:

import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);

Ось приклад CSS модулів веб- упаковки


FYI: Якщо ви використовуєте Meteor, ознайомтеся з цим пакетом: github.com/nathantreid/meteor-css-modules . Я використовую його, маючи досі великий успіх.
Спіраліс

Це прекрасний спосіб стильової реакції компонентів, але не зовсім дає вам змогу контролювати стилі вбудованих. Наприклад, ви не можете змінювати :hoverстилі під час виконання, як ви можете з Radium чи іншимonMouseOver базованого рішення
Чарлі Мартін,

4

onMouseOver і onMouseLeave з setState спочатку здалися мені трохи накладними, але оскільки так реагує, мені здається найпростішим і чистішим рішенням.

наприклад, надання тематичного CSS-сервера, також є хорошим рішенням і підтримує більш чисті компоненти реакції.

якщо вам не потрібно додавати динамічні стилі до елементів (наприклад, для тематизації), ви взагалі не повинні використовувати вбудовані стилі, а натомість використовувати класи css.

Це традиційне правило html / css, щоб підтримувати html / JSX чистим та простим.


4

Простий спосіб - використання потрійного оператора

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={this.state.hover ? {"backgroundColor": 'red'}: {"backgroundColor": 'blue'}} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

1

За допомогою гачків:

const useFade = () => {
  const [ fade, setFade ] = useState(false);

  const onMouseEnter = () => {
    setFade(true);
  };

  const onMouseLeave = () => {
    setFade(false);
  };

  const fadeStyle = !fade ? {
    opacity: 1, transition: 'all .2s ease-in-out',
  } : {
    opacity: .5, transition: 'all .2s ease-in-out',
  };

  return { fadeStyle, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeStyle, ...fadeProps } = useFade();

  return (
    <Paper
      style={{...fadeStyle, ...style}}
      {...fadeProps}
    >
      {...}
    </Paper>
  );
};

0

Я використовую досить гарне рішення для цього в одному з моїх останніх додатків, що працює для моїх цілей, і я вважаю, що це швидше, ніж написання спеціальних функцій налаштування курсору у ванілі js (хоча, я визнаю, можливо, це не найкраща практика в більшості середовищ ..) Отже, на випадок, якщо ви все-таки зацікавлені, тут іде.

Я створюю батьківський елемент лише для того, щоб утримувати вбудовані стилі JavaScript, потім дитина з класним іменем або ідентифікатором, на який мій таблиця стилів css зав'яжеться, і напише стиль наведення в мій виділений файл css. Це працює тому, що більш деталізований дочірній елемент отримує вбудовані js стилі у спадок, але має свої стилі наведення курсору, перекриті файлом css.

Таким чином, мій фактичний файл css існує лише з метою проведення ефектів наведення, більше нічого. Це робить його досить стислим і простим в управлінні, і дозволяє мені робити важкі підйоми в моїх стильових компонентах In-line React.

Ось приклад:

const styles = {
  container: {
    height: '3em',
    backgroundColor: 'white',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    borderBottom: '1px solid gainsboro',
  },
  parent: {
    display: 'flex',
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    color: 'darkgrey',
  },
  child: {
    width: '6em',
    textAlign: 'center',
    verticalAlign: 'middle',
    lineHeight: '3em',
  },
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div style={styles.container}>
      <div style={styles.parent}>
        {menuOptions.map((page) => <div className={'navBarOption'} style={styles.child} key={page}>{page}</div> )}
      </div>
    </div>
  );
};


ReactDOM.render(
  <NavBar/>,
  document.getElementById('app')
);
.navBarOption:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Зауважте, що в стилі "child" inline немає набору властивостей "color". Якби це було, це не спрацювало, тому що стиль вбудованої системи мав би перевагу над моєю таблицею стилів.


0

Я не на 100% впевнений, що це відповідь, але її хитрість я використовую для імітації CSS: ефект наведення курсором із кольорами та зображеннями в рядку.

`This works best with an image`

class TestHover extends React.PureComponent {
render() {
const landingImage = {     
"backgroundImage": "url(https://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg)",
"BackgroundColor": "Red", `this can be any color`
"minHeight": "100%",
"backgroundAttachment": "fixed",
"backgroundPosition": "center",
"backgroundRepeat": "no-repeat",
"backgroundSize": "cover", 
"opacity": "0.8", `the hove trick is here in the opcaity slightly see through gives the effect when the background color changes`
    }

  return (
    <aside className="menu">
        <div className="menu-item">
          <div style={landingImage}>SOME TEXT</div>
        </div>
    </aside>
      ); 
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

.menu {
top: 2.70em;
bottom: 0px;
width: 100%;
position: absolute;
}

.menu-item {
cursor: pointer;
height: 100%;
font-size: 2em;
line-height: 1.3em;
color: #000;
font-family: "Poppins";
font-style: italic;
font-weight: 800;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}

Перш ніж навести курсор

.menu-item:nth-child(1) {
color: white;
background-color: #001b37;
} 

На наведення

.menu-item:nth-child(1):hover {
color: green;
background-color: white;
}

Приклад: https://codepen.io/roryfn/pen/dxyYqj?editors=0011


0
<Hoverable hoverStyle={styles.linkHover}>
  <a href="https://example.com" style={styles.link}>
    Go
  </a>
</Hoverable>

Де Поважний визначається як:

function Hoverable(props) {
  const [hover, setHover] = useState(false);

  const child = Children.only(props.children);

  const onHoverChange = useCallback(
    e => {
      const name = e.type === "mouseenter" ? "onMouseEnter" : "onMouseLeave";
      setHover(!hover);
      if (child.props[name]) {
        child.props[name](e);
      }
    },
    [setHover, hover, child]
  );

  return React.cloneElement(child, {
    onMouseEnter: onHoverChange,
    onMouseLeave: onHoverChange,
    style: Object.assign({}, child.props.style, hover ? props.hoverStyle : {})
  });
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.