{"id":2325,"date":"2022-01-26T10:21:45","date_gmt":"2022-01-26T10:21:45","guid":{"rendered":"https:\/\/lvboard.infostore.in.ua\/?p=2325"},"modified":"2022-01-26T10:21:45","modified_gmt":"2022-01-26T10:21:45","slug":"how-to-create-modern-cards-using-react-and-tailwind","status":"publish","type":"post","link":"https:\/\/lvboard.infostore.in.ua\/?p=2325","title":{"rendered":"How to Create Modern Cards using React and Tailwind"},"content":{"rendered":"\n<p>One of my favorite components is undoubtedly cards and the reasons are very simple, they can have many uses.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>In the same way that it can be used for informative content (such as brief descriptions), it can also be used to focus the user&#8217;s attention momentarily (such as a post on social media) or so that the user can take an action.<\/p>\n\n\n\n<p>When designing a card we need to pay attention to some aspects:<\/p>\n\n\n\n<ul><li>All content must be contained in a single element;<\/li><li>You don&#8217;t need to have other auxiliary elements to give some context to the card&#8217;s content;<\/li><\/ul>\n\n\n\n<p>From these small points we only need to pay attention to a few aspects in terms of the element&#8217;s anatomy.<\/p>\n\n\n\n<p>Obviously, many of the elements end up being optional and for that same reason today I&#8217;m only going to focus on just these:<\/p>\n\n\n\n<ul><li>Container &#8211; contains all the elements of the card and generally these same elements dictate the size of the card however, I like to do the opposite which is to define the maximum space they can occupy;<\/li><li>Thumbnail &#8211; it&#8217;s an important visual element, however this article will be for stylistic reasons;<\/li><li>Buttons &#8211; usually the buttons are grouped in a single space and each button corresponds to an action that the user can take;<\/li><\/ul>\n\n\n\n<p>And one of the aspects that I find interesting is that it&#8217;s a component that generally has great behaviors in terms of responsiveness.<\/p>\n\n\n\n<p>Anyway, these are just a few aspects that I take into account when working with interface elements, so I recommend reading this <a href=\"https:\/\/material.io\/components\/cards\">Material Design<\/a> page which explains in detail what kind of behavior this component should have.<\/p>\n\n\n\n<h2><a href=\"https:\/\/dev.to\/franciscomendes10866\/how-to-create-modern-cards-using-react-and-tailwind-2ded#todays-example\"><\/a> Today&#8217;s example<\/h2>\n\n\n\n<p>In today&#8217;s example we will make a simple card, but in my opinion it has a very different design when compared to many libraries and frameworks. A behavior I recommend adopting is to spend a few minutes daily to see designs that you find interesting and I tried to copy them. I hope that at the end of today&#8217;s article you have a similar result:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--f7dHlgKX--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880\/https:\/\/res.cloudinary.com\/dj5iihhqv\/image\/upload\/v1636823266\/Kapture_2021-11-13_at_16.58.08-min_sqbpz7.gif\"><img src=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--f7dHlgKX--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880\/https:\/\/res.cloudinary.com\/dj5iihhqv\/image\/upload\/v1636823266\/Kapture_2021-11-13_at_16.58.08-min_sqbpz7.gif\" alt=\"card final result\"\/><\/a><\/figure>\n\n\n\n<h1><a href=\"https:\/\/dev.to\/franciscomendes10866\/how-to-create-modern-cards-using-react-and-tailwind-2ded#lets-code\"><\/a> Let&#8217;s code<\/h1>\n\n\n\n<p>The framework we are going to use today is Tailwind CSS and along with this framework we are going to use other tools such as classnames and react-icons.<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install classnames react-icons\n<\/code><\/pre>\n\n\n\n<p>After that we will create a file that contains the contents of the cards.<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ @src\/data\/posts.js\n\nexport default &#91;\n  {\n    title: \"Rogue's Rise\",\n    likes: Math.floor(Math.random() * (50 - 0) + 0),\n    image: \"https:\/\/bit.ly\/3BQdTqk\",\n  },\n  {\n    title: \"Fool's End\",\n    likes: Math.floor(Math.random() * (50 - 0) + 0),\n    image: \"https:\/\/bit.ly\/3CQFPvv\",\n  },\n  {\n    title: \"A Greater Power\",\n    likes: Math.floor(Math.random() * (50 - 0) + 0),\n    image: \"https:\/\/bit.ly\/3ERuyMd\",\n  },\n  {\n    title: \"2099: Oasis\",\n    likes: Math.floor(Math.random() * (50 - 0) + 0),\n    image: \"https:\/\/bit.ly\/3CQKSwb\",\n  },\n];\n<\/code><\/pre>\n\n\n\n<p>Now we can start working on our card but first let&#8217;s create the styles for our component:<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* @src\/components\/Card.module.css *\/\n\n.wrapper {\n  @apply bg-white hover:bg-gray-800 shadow-xl hover:shadow-none cursor-pointer w-80 rounded-3xl flex flex-col items-center justify-center;\n}\n\n.wrapperAnime {\n  @apply transition-all duration-500 ease-in-out;\n}\n\n.header {\n  @apply relative mt-2 mx-2;\n}\n\n.imageWrapper {\n  @apply h-56 rounded-2xl overflow-hidden;\n}\n\n.image {\n  @apply object-cover w-full h-full;\n}\n\n.textWrapper {\n  @apply pt-10 pb-6 w-full px-4;\n}\n\n.text {\n  @apply font-medium leading-none text-base tracking-wider text-gray-400;\n}\n\n.badgeWrapper {\n  @apply absolute bottom-0 left-0 -mb-4 ml-3 flex flex-row;\n}\n\n.dangerBadge {\n  @apply h-10 w-10 flex items-center justify-center text-xl bg-white hover:bg-red-500 text-red-500 hover:text-white rounded-2xl shadow-xl;\n}\n\n.primaryBadge {\n  @apply h-10 w-16 ml-2 bg-white hover:bg-blue-600 flex items-center justify-center font-medium text-blue-600 hover:text-white rounded-2xl shadow-xl;\n}\n\n.counter {\n  @apply text-gray-800 ml-2;\n}\n\n.badgeAnime {\n  @apply transform-gpu translate-y-0 hover:-translate-y-1 transition-all duration-300 ease-in-out;\n}\n<\/code><\/pre>\n\n\n\n<p>Now we can start working on our component&#8217;s jsx. Our component will receive four props, which will be the title, the number of likes, the order of the array element and the image.<\/p>\n\n\n\n<p>After that we can import our icons and we can start applying the styles of our component:<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ @src\/components\/Card.jsx\n\nimport React from \"react\";\nimport classNames from \"classnames\";\nimport { AiFillHeart } from \"react-icons\/ai\";\nimport { BsChatSquareFill } from \"react-icons\/bs\";\n\nimport styles from \".\/Card.module.css\";\n\nconst Card = ({ title, likes, order, image }) =&gt; {\n  return (\n    &lt;div className={classNames(&#91;styles.wrapper, styles.wrapperAnime])}&gt;\n      &lt;div className={styles.header}&gt;\n        &lt;div className={styles.imageWrapper}&gt;\n          &lt;img src={image} className={styles.image} alt=\"\" \/&gt;\n        &lt;\/div&gt;\n        &lt;div className={styles.badgeWrapper}&gt;\n          &lt;div\n            className={classNames(&#91;styles.dangerBadge, styles.badgeAnime])}\n          &gt;\n            &lt;AiFillHeart \/&gt;\n          &lt;\/div&gt;\n          &lt;div\n            className={classNames(&#91;\n              styles.primaryBadge,\n              styles.badgeAnime,\n              \"group\",\n            ])}\n          &gt;\n            &lt;BsChatSquareFill \/&gt;\n            &lt;span\n              className={classNames(&#91;styles.counter, \"group-hover:text-white\"])}\n            &gt;\n              {likes}\n            &lt;\/span&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n      &lt;div className={styles.textWrapper}&gt;\n        &lt;h1 className={styles.text}&gt;{`${order}. ${title}`}&lt;\/h1&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  );\n};\n\nexport default Card;\n<\/code><\/pre>\n\n\n\n<p>Last but not least we have to go to our entry file (which in this case is App.jsx) and we will have the following styles:<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* @src\/App.module.css *\/\n\n.section {\n  @apply bg-gray-100 h-full md:h-screen w-full;\n}\n\n.container {\n  @apply container mx-auto px-0 md:px-4 py-4;\n}\n\n.layout {\n  @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 justify-items-center gap-4;\n}\n<\/code><\/pre>\n\n\n\n<p>Now in our App.jsx we&#8217;re going to import our data from the posts and our Card component that we created, then we&#8217;re going to loop and pass in the necessary props.<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ @src\/App.jsx\n\nimport React from \"react\";\n\nimport styles from \".\/App.module.css\";\nimport Card from \".\/components\/Card\";\nimport posts from \".\/data\/posts\";\n\nconst App = () =&gt; {\n  return (\n    &lt;main className={styles.section}&gt;\n      &lt;section className={styles.container}&gt;\n        &lt;div className={styles.layout}&gt;\n          {posts.map((element, index) =&gt; (\n            &lt;Card\n              key={index}\n              title={element.title}\n              likes={element.likes}\n              order={index + 1}\n              image={element.image}\n            \/&gt;\n          ))}\n        &lt;\/div&gt;\n      &lt;\/section&gt;\n    &lt;\/main&gt;\n  );\n};\n\nexport default App;\n<\/code><\/pre>\n\n\n\n<h2><a href=\"https:\/\/dev.to\/franciscomendes10866\/how-to-create-modern-cards-using-react-and-tailwind-2ded#conclusion\"><\/a> Conclusion<\/h2>\n\n\n\n<p>As always, I hope you found it interesting. If you noticed any errors in this article, please mention them in the comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of my favorite components is undoubtedly cards and the reasons are very simple, they can have many uses.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[65,189],"_links":{"self":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2325"}],"collection":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2325"}],"version-history":[{"count":1,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2325\/revisions"}],"predecessor-version":[{"id":2326,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/2325\/revisions\/2326"}],"wp:attachment":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}