cssreactjsfluent-uifluentui-react

React Youtube card. Playbutton not rendering properly in CSS


I have below example where I am trying to render a YouTube card. The issue I am facing is that the play button white background is not adjusting into the play icon that I am setting through my CSS styles. I am trying to undertand why that is not working.

Also, when I hover the card, I should see a background that says Video Test, but that never gets rendered.

https://stackblitz.com/edit/ndu1t6?file=src%2Fexample.tsx,src%2FYoutubeCard.tsx

Why is this part giving the trouble?

'&:hover': {
  transform: 'scale(1.05)',
  boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
},
'&:hover $overlay': {
  backgroundColor: 'rgba(0, 0, 0, 0.6)',
},
'&:hover $textOverlay': {
  opacity: 1,
},
'&:hover $playButton': {
  opacity: 0,
},

Solution

  • I think the underlying issues are:

    1. Specificity: some of your styled are being overwritten by the fluentui css styled. By adding !important you can force your styles to be used.
    2. The overlay, textOverlay and playButton should probably not be seperated into sibling div-elements, instead you can group them together.

    Here is my code (although the styling might not be exactly what you intended to do):

    import { makeStyles } from '@fluentui/react-components';
    
    export const useVideoYoutubeCardStyles = makeStyles({
        card: {
            width: '300px',
            border: '1px solid #ccc',
            borderRadius: '8px',
            overflow: 'hidden',
            position: 'relative',
            cursor: 'pointer',
            transition: 'transform 0.3s, box-shadow 0.3s',
            '&:hover': {
                transform: 'scale(1.05)',
                boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
            },
        },
        overlay: {
            position: 'absolute',
            top: '0px',
            width: '100%',
            height: '100%',
            backgroundColor: 'rgba(0, 0, 0, 0)',
            transition: 'background-color 0.3s',
            '&:hover': {
                // backgroundColor: 'rgba(0, 0, 0, 0.6)', <-- moved this to textOverlay:hover
            },
        },
        textOverlay: {
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            color: 'white',
            fontSize: '14px',
            fontWeight: 100,
            textAlign: 'center',
            opacity: 0,
            transition: 'opacity 0.3s',
            fontFamily: 'Arial, sans-serif',
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
    
            '&:hover': {
                opacity: 1,
                backgroundColor: 'rgba(0, 0, 0, 0.6)' //<-- this comes from overlay
            },
        },
        playButton: {
            position: 'absolute',
            top: '30%',
            left: '30%',
            width: '100px !important', //<-- add !important because they are otherwise being overwritten
            height: '100px !important', //<-- add !important because they are otherwise being overwritten
            backgroundColor: 'rgba(255, 255, 255, 0.8)',
            borderRadius: '50%',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
            transition: 'opacity 0.3s',
        },
        playButtonTriangle: {
            position: 'absolute',
            left: '37px',
            top: '28px',
            width: '30px',
            height: '0px',
            borderLeft: '30px solid gray',
            borderTop: '20px solid transparent',
            borderBottom: '20px solid transparent',
            marginLeft: '3px',
        },
    });

    import { Card, CardPreview, Image } from '@fluentui/react-components';
    import * as React from 'react';
    import { useVideoYoutubeCardStyles } from './YoutubeCard.styled.tsx';
    
    export type YoutubeCardProps = {
        card: string;
    };
    export const YoutubeCard: React.FC<YoutubeCardProps> = React.memo((_) => {
        const styles = useVideoYoutubeCardStyles();
        const videoId = 'h3BKjZMGoIw';
        const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
    
        const handleCardClick = () => {
            window.open(`https://www.youtube.com/watch?v=${videoId}`, '_blank');
        };
    
        return (
            <Card className={styles.card} onClick={handleCardClick}>
                <CardPreview>
                    <Image
                        src={thumbnailUrl}
                        alt="YouTube Thumbnail"
                        style={{ width: '100%' }}
                    />
                    {/*black overlay when hovering*/}
                    <div className={styles.overlay}></div>
                    <div id="textOverlay" className={styles.textOverlay}>
                        <p style={{margin: 0}}>Video Test</p>
                        <div id="playButton" className={styles.playButton}>
                            <div className={styles.playButtonTriangle}></div>
                        </div>
                        {/*    <p style={{ margin: 0 }}>Vide Test Test</p>*/}
                    </div>
                </CardPreview>
            </Card>
        );
    });
    
    YoutubeCard.displayName = 'YoutubeCard';