<div id="root"></div>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&family=Patua+One&display=swap');

.font-Patua {
  font-family: 'Patua One', cursive;
  font-size: 20px;
}

body {
  background-color: #c0a695;
  color: #f9fbf8;
  font-family: 'Open Sans', sans-serif;
}
#root {
  width: 100%;
  display: flex;
  justify-content: center;
}
.main-container {
  background-color: #5b4a42;
}

.item-title {
  color: #c2976c;
}

.item-description {
  color: #d2d0ce;
}

.address,
.item-price {
  background: #51413a;
}
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: linear-gradient(
      180deg,
      rgba(34, 34, 34, 0.7) 0%,
      #5b4a42 100%
    ),
    url('https://assets.codepen.io/t-1/nathan-dumlao-6VhPY27jdps-unsplash.jpg');
  height: 500px;
  background-position: center;
  background-repeat: no-repeat;
  background-size: auto 100%;

}
@media (min-width: 640px) {
  .hero {
    justify-content: space-between;
    align-items: flex-end;
    height: 300px;
    background-position: center;
    background-repeat: no-repeat;
    background-size: 100% auto;
  }
}
View Compiled
const data = [
  {
    key: 0,
    title: 'Coffee',
    description: {
      left: {
        text: 'Small : $2',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-coffee.png',
        scaleDown: true,
      },
      right: {
        text: 'Large : $4',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-coffee.png',
      },
    },
    list: [
      {
        title: 'House Blend',
        description: 'Smoky, strong, and assertive, just like us.',
      },
      {
        title: 'Organic French Roast',
        description: 'Smooth and mellow with hints of molasses.',
      },
      {
        title: 'Organic Decaf',
        description:
          "Full bodied and rich, we promise you won't miss the caffiene.",
      },
    ],
  },
  {
    key: 1,
    title: 'Tea',
    description: {
      left: {
        text: 'Per Cup : $2',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-tea.png',
      },
      right: {
        text: '$200 if you break the cup',
        image:
          'https://assets.codepen.io/3685267/react-cafe-menu-tea-broken.png',
      },
      text: 'Served to brave people in our notorious antique tea cups.',
    },
    list: [
      {
        title: 'Earl Grey ',
        description: 'Black tea fragranced with bergamot.',
      },
      {
        title: 'Ginger Hibiscus',
        description: 'Floral, tart, and spicy. Caffeine free.',
      },
      {
        title: 'Cascade Green',
        description:
          'A blend of green teas hand selected by our master teamaker.',
      },
      {
        title: 'Chamomile',
        description:
          'Soothing and slightly sweet. Try it with honey! Caffeine free.',
      },
    ],
  },
  {
    key: 2,
    title: 'Espresso Drinks',
    description: {
      left: {
        text: 'Small : $3',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-espresso.png',
        scaleDown: true,
      },
      right: {
        text: 'Large : $5',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-espresso.png',
      },
    },
    list: [
      {
        title: 'Machiatto',
        description:
          'Espressso and steamed milk, served in a demitasse cup. (Size Small Only)',
      },
      {
        title: 'Latte',
        description:
          'Espresso with steamed milk, and sometimes a little art on top. ',
      },
      {
        title: 'Mocha',
        description:
          'Espresso with steamed chocolate milk and whipped cream. Also available with white chocolate milk.',
      },
      {
        title: 'Americano',
        description: '1 shot espresso, two shots hot water.',
      },
    ],
  },

  {
    key: 3,
    title: 'From the Bakery',
    description: {
      left: {
        text: 'Cookies : $2',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-cookie.png',
      },
      right: {
        text: 'Muffins & Pastries : $3',
        image: 'https://assets.codepen.io/3685267/react-cafe-menu-muffin.png',
      },
    },
    list: [
      {
        title: "Mallory's Famous Snickerdoodles",
        description:
          "Creamy cinnamony goodness made from scratch with our founder Mallory's prizewinning recipe.",
      },
      {
        title: 'Oatmeal Cookie',
        description:
          'Packed with rolled oats, raisins, and cranberries, these monster cookies are (almost) good for ya!',
      },
      {
        title: 'Mixed Berry Muffins',
        description:
          'Filled with the best berries of the season and topped with a crumb crust.',
      },
      {
        title: 'Croissant',
        description:
          'Our oversized croissants are buttery, flaky, and usually all sold out by 7 a.m.',
      },
    ],
  },
];

const title = 'The Cascade Cafe'.split('');
const est = 'Est - 1896'.split('');

est.reverse();

function App() {
  return (
    <div className="py-0 sm:py-10 max-w-screen-lg">
      <div className=" main-container rounded-none sm:rounded overflow-hidden">
        <div className="hero flex-col sm:flex-row">
          <Header />
          <Hours />
        </div>
        <div className="flex flex-wrap">
          {data.map((item, index) => (
            <MenuSection key={item.key} item={item} index={index} />
          ))}
        </div>
        <Address />
      </div>
    </div>
  );
}

function Header() {
  return (
    <div
      className=""
      style={{ width: '300px', height: '300px', position: 'relative' }}
    >
      {title.map((i, index) => (
        <div
          key={index}
          className="flex justify-center font-Patua"
          style={{
            position: 'absolute',
            height: '205px',
            width: '40px',
            left: '50%',
            top: '50%',
            transform: `translate(-50%, -50%) rotate(${
              index * 10 - ((title.length - 1) * 10) / 2
            }deg)`,
          }}
        >
          {i}
        </div>
      ))}
      {est.map((i, index) => (
        <div
          key={index}
          className="flex justify-center items-end font-Patua"
          style={{
            position: 'absolute',
            height: '205px',
            width: '40px',
            left: '50%',
            top: '50%',
            transform: `translate(-50%, -50%) rotate(${
              index * 10 - ((est.length - 1) * 10) / 2
            }deg)`,
          }}
        >
          {i}
        </div>
      ))}
      <div
        className=""
        style={{
          position: 'absolute',
          left: '50%',
          top: '50%',
          transform: 'translate(-50%, -50%)',
          border: '4px solid #fff',
          width: '220px',
          height: '220px',
          borderRadius: '999px',
        }}
      />
      <div
        className=""
        style={{
          position: 'absolute',
          left: '50%',
          top: '50%',
          transform: 'translate(-50%, -50%)',
          border: '2px solid #fff',
          width: '140px',
          height: '140px',
          borderRadius: '999px',
        }}
      />
      <div
        className=""
        style={{
          position: 'absolute',
          left: '50%',
          top: '50%',
          transform: 'translate(-50%, -50%)',
          width: '120px',
          height: '120px',
          borderRadius: '999px',
        }}
      >
        <svg
          width="100%"
          height="100%"
          viewBox="0 0 252 252"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path
            d="M125.51 0C56.74 0 1 56.31 1 125.78C1 195.25 56.74 251.56 125.51 251.56C194.28 251.56 250.02 195.25 250.02 125.78C250.02 56.31 194.28 0 125.51 0ZM114.45 24.78C118.24 25.85 120.99 30.64 124.17 33.78H124.24C127.42 30.65 130.17 25.86 133.96 24.78C138.15 23.59 143.47 34.18 140.74 39.97C136.65 48.68 131.31 56.88 125.54 66.57C125.18 67.43 124.81 68.29 124.43 69.19L124.21 68.81L123.98 69.19C123.6 68.29 123.24 67.43 122.87 66.57C117.11 56.88 111.76 48.68 107.67 39.97C104.94 34.18 110.26 23.59 114.45 24.78V24.78ZM108.59 55.26L125.34 81.56L142.14 52.22C151.97 75.84 128.14 85.63 125.35 102.98C109.29 87.23 101.65 66.31 108.59 55.26ZM98.5 77.45L124.64 122.15C132.06 107.29 140.57 90.23 149.13 73.06C156.91 84.8 155.75 107.34 146.54 116.8C139.67 123.85 132.24 130.33 125.54 136.66C117.69 129.72 109.47 122.73 101.54 115.39C91.35 105.99 90.04 90.03 98.5 77.45ZM105.94 132.59C114.94 139.02 119.42 148.21 121.08 159.04C115.37 146.58 106.5 137.85 92.38 134.68L116.6 160.68C91.91 149.38 74.6 132.54 74.6 102.97C80.31 118.32 94.25 124.2 105.94 132.59V132.59ZM57.48 124.59C60.48 129.17 62.79 132.48 64.93 135.88C72.93 148.59 84.57 155.28 98.93 158.68C113.86 162.23 122.02 171.91 123.39 187.82C118.6 175.65 109.68 172.39 100.27 169.65C91.43 167.04 82.72 164 73.34 160.95C78.61 171.02 87.49 175.36 97.24 178.74C103.07 180.74 109.47 182.42 114.17 186.12C118.87 189.82 121.76 195.85 124.17 202.03C116.17 189.71 103.51 187.03 90.96 183.72C63.06 176.34 48.56 151.42 57.48 124.59V124.59ZM121.41 232.59C113.19 227.31 105.47 220.99 96.75 216.78C86.44 211.78 74.95 209.34 64.57 204.47C44.38 195.01 32.57 170.41 38.22 148.72C38.6991 146.73 39.547 144.847 40.72 143.17C45.67 169.99 64.12 180.68 87.43 186.17C99.77 189.08 110.98 194.61 118.97 205.08C121.526 208.451 122.901 212.57 122.88 216.8C120.99 214.8 119.42 212.21 117.15 210.8C109.08 205.8 101.79 197.96 92.48 196.52C79.3653 194.211 66.9422 188.967 56.14 181.18C60.14 188.07 60.39 189.33 68.82 197.53C75.68 204.2 83.5 203.53 92.71 206.29C106.19 210.36 118.79 215.22 124.28 230.04C124.68 231.1 126.1 231.78 126.19 234.55C124.541 234.067 122.941 233.431 121.41 232.65V232.59ZM139.73 130.59C150.48 120.02 163.95 111.7 167.37 94.94C172.11 125.48 156.88 145.67 133.16 161.34L154.07 130.65C139.98 136.21 132.21 146.65 128.28 160.46C128.27 148.96 131.5 138.73 139.73 130.65V130.59ZM152.47 163.01C138.85 166.93 139.91 168.69 132.04 179.85C131.84 179.75 131.64 179.67 131.44 179.59C134.01 174.4 136.52 169.17 140.19 164.96C145.63 158.71 153.4 154.59 159.67 148.96C169.47 140.21 178.86 130.96 187.98 122.4C192.98 132.54 189.73 152.51 177.72 163.28C168.81 171.28 157.83 176.92 147.67 183.44C141.99 187.08 136.2 190.44 130.59 193.82C130.777 191.345 131.669 188.975 133.16 186.99C139.08 180.93 142.48 174.15 148.84 171.48C155.84 168.54 163.94 160.78 169.21 155.31C168.52 154.76 160.14 160.44 152.47 163.06V163.01ZM213.04 169.39C209.48 184.69 198.94 194.39 185.77 201.18C177.77 205.29 169.11 208.08 160.63 211.18C151.71 214.42 142.63 217.3 131.32 221.18C148.19 202.79 175.32 205.98 189.89 186.58L131.27 211.19C132.76 204.99 138.08 199.8 145.08 196.28C154 191.79 163.21 187.91 172.16 183.5C190.33 174.5 203.02 161.3 204.5 137.02C214.47 147.88 215.64 158.33 213.04 169.44V169.39Z"
            fill="#ffffff"
          />
        </svg>
      </div>
    </div>
  );
}

function Hours() {
  return (
    <div className="pb-4 pr-4">
      <table className="hours justify-self-end">
        <thead>
          <tr>
            <th colSpan="2">Hours</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td className="pr-4">Mon. - Thurs.</td>
            <td>6 a.m. - 9 p.m.</td>
          </tr>
          <tr>
            <td>Fri. - Sat.</td>
            <td>6 a.m. - 11 p.m.</td>
          </tr>
          <tr>
            <td>Sunday</td>
            <td>8 a.m. - 2 p.m.</td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}

function MenuSection({
  item: {
    title: mainTitle,
    list,
    description: {
      left: { text: titleLeft, image: imageLeft, scaleDown },
      right: { text: titleRight, image: imageRight },
      text: subTitle,
    },
  },
  index,
}) {
  return (
    <div
      className={`w-full md:w-1/2 p-6 flex-shrink-0 ${index > 1 && 'mt-16'}`}
    >
      <h2 className="item-title text-2xl font-bold">{mainTitle}</h2>

      <div className="item-price flex justify-between items-center p-2 mt-3 rounded">
        <div className="flex items-center">
          <img
            src={imageLeft}
            alt=""
            className={scaleDown ? 'w-5 h-5' : 'w-8 h-8'}
          />
          <div className="ml-3 text-sm md:text-base">{titleLeft}</div>
        </div>
        <div className="flex items-center">
          <div className="mr-3 text-sm md:text-base">{titleRight}</div>
          <img src={imageRight} alt="" className="w-8 h-8 " />
        </div>
      </div>
      <div className="mt-4">{subTitle}</div>
      <dl>
        {list.map(({ title, description }) => (
          <React.Fragment key={title}>
            <dt className="text-lg font-semibold mt-3">{title}</dt>
            <dd className="description item-description italic">
              <p>{description}</p>
            </dd>
          </React.Fragment>
        ))}
      </dl>
    </div>
  );
}

function Address() {
  return (
    <address className="flex py-3 justify-center mt-6 flex-wrap address">
      <div className="flex">
        <svg
          viewBox="0 0 384 512"
          width="15"
          title="map-marker-alt"
          fill="currentColor"
        >
          <path d="M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z" />
        </svg>
        <p className="ml-4">123 Main Street &middot; Smalltown, PA</p>
      </div>
      <div className="flex  mt-2 md:mt-0">
        <svg
          viewBox="0 0 512 512"
          width="15"
          title="phone-alt"
          fill="currentColor"
          className="ml-8"
        >
          <path d="M497.39 361.8l-112-48a24 24 0 0 0-28 6.9l-49.6 60.6A370.66 370.66 0 0 1 130.6 204.11l60.6-49.6a23.94 23.94 0 0 0 6.9-28l-48-112A24.16 24.16 0 0 0 122.6.61l-104 24A24 24 0 0 0 0 48c0 256.5 207.9 464 464 464a24 24 0 0 0 23.4-18.6l24-104a24.29 24.29 0 0 0-14.01-27.6z" />
        </svg>
        <a href="4125550100" className="ml-4">
          412-555-0100
        </a>
      </div>
    </address>
  );
}

ReactDOM.render(<App />,
document.getElementById("root"))
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.4/tailwind.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js