Встроенные стили CSS в React: как реализовать a: hover?

Мне очень нравится встроенный шаблон CSS в React и решил использовать его.

Однако вы не можете использовать :hover и аналогичные селектора. Итак, что лучший способ реализовать подсветку при наведении при использовании встроенных стилей CSS?

Одно предложение от #reactjs состоит в том, чтобы иметь компонент Clickable и использовать его следующим образом:

<Clickable>
    <Link />
</Clickable>

Clickable имеет состояние hovered и передает его в качестве опоры для ссылки. Однако Clickable (способ, которым я его реализовал) обертывает Link в div, чтобы он мог установить для него onMouseEnter и onMouseLeave. Это делает вещи немного сложными, хотя (например, span, завернутый в div, ведет себя иначе, чем span).

Есть ли более простой способ?

Ответ 1

Я в той же ситуации. На самом деле нравится шаблон сохранения стиля в компонентах, но состояния зависания кажутся последним препятствием.

Что я сделал, это написать mixin, который вы можете добавить к своему компоненту, который нуждается в состояниях зависания. Этот mixin добавит новое свойство hovered к состоянию вашего компонента. Он будет установлен в true, если пользователь наведет над основным DOM node компонента и вернет его к false, если пользователи покинут элемент.

Теперь в вашей функции рендеринга компонента вы можете сделать что-то вроде:

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

Теперь каждый раз, когда состояние состояния hovered изменяется, компонент будет перезагружен.

Я также создаю репозиторий sandbox для этого, который я использую для тестирования некоторых из этих шаблонов. Проверьте это, если вы хотите увидеть пример моей реализации.

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

Ответ 2

Я думаю, что 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>
    )
  }

Затем вы можете использовать состояние зависания (true/false), чтобы изменить стиль ссылки.

Ответ 3

Вы можете использовать Radium - это инструмент с открытым исходным кодом для встроенных стилей с ReactJS. Он добавляет именно нужные вам селектор. Очень популярный, проверьте это - Радиум на ганне

Ответ 4

Полная поддержка CSS - это именно причина этого огромного количества библиотек CSSinJS, чтобы сделать это эффективно, вам нужно генерировать фактические CSS, а не встроенные стили. Кроме того, встроенные стили намного медленнее реагируют в более крупной системе. Отказ от ответственности - я поддерживаю JSS.

Ответ 5

Made Style It - частично - по этой причине (из-за несогласия с реализацией других библиотек/синтаксиса и встроенных стилей отсутствует поддержка префикса значений свойств). Поверьте, мы должны иметь возможность просто писать 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;

Ответ 6

Что касается styled-components и response-router v4, вы можете сделать это:

import {NavLink} from 'react-router-dom'

const Link = styled(NavLink)'     
  background: blue;

  &:hover {
    color: white;
  }
'

...
<Clickable><Link to="/somewhere">somewhere</Link></Clickable>

Ответ 7

Оформить покупку Typestyle, если вы используете React с Typescript.

Ниже приведен пример кода для: hover

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>

Ответ 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>
    )
  }

Ответ 9

Вы можете использовать css modules в качестве альтернативы, а также react-css-modules для сопоставления имен классов.

Таким образом, вы можете импортировать свои стили следующим образом и использовать обычные 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

Ответ 10

Поздно на вечеринку, но прийти с решением. Вы можете использовать "&", чтобы определить стили для hover 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"
    }
  },

Ответ 11

onMouseOver и onMouseLeave с setState поначалу показались мне немного непосильными, но, как работает реакция, мне кажется, это самое простое и чистое решение.

рендеринг тематических css серверов, например, также является хорошим решением и обеспечивает более чистую реакцию компонентов.

Если вам не нужно добавлять динамические стили к элементам (например, для темы), вам не следует использовать встроенные стили вообще, а вместо этого использовать классы CSS.

Это традиционное правило html/css, позволяющее сохранять html/JSX чистым и простым.

Ответ 12

Это может быть хорошим подспорьем для использования встроенного стиля внутри реагирующего компонента (а также с помощью: hover CSS-функции):

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

Ответ 13

Самый простой способ - использование троичного оператора

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>
    )
  }

Ответ 14

Я использую довольно хак-иш-решение для этого в одном из моих последних приложений, которое работает для моих целей, и я нахожу его быстрее, чем писать пользовательские настройки параметров зависания в vanilla js (хотя, я признаю, может быть, не лучшая практика в большинстве сред..) Итак, в случае, если вы все еще заинтересованы, здесь идет.

Я создаю родительский элемент только для того, чтобы удержать встроенные стили javascript, а затем дочерний элемент с именем класса или id, который моя таблица стилей CSS будет запираться и писать стиль зависания в моем выделенном файле css. Это работает, потому что более подробный дочерний элемент получает встроенные стили js через наследование, но имеет стили hover, переопределенные css файлом.

Итак, мой фактический файл css существует с единственной целью - удерживать эффекты зависания, ничего другого. Это делает его довольно кратким и легким в управлении, и позволяет мне делать тяжелую работу в моих встроенных стилях 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>

Ответ 15

С использованием крючков:

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>
  );
};

Ответ 16

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

'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

Ответ 17

Самый простой способ - просто добавить тег абзаца в ссылку и стиль разбора в p. <Link to='/'><p style={{ color: '#000000' }}>Some text</p></Link>