<div class="cards">
  <div class="card">
    <img src="https://picsum.photos/200/100" alt="..." class="card-img-top">
    <div class="card-body">
      <h2 class="card-title">Selectable Title 1</h2>
      <p>
        You can select this text even though the whole card is clickable. <a href="#1">Read more...</a>
      </p>
    </div>
  </div>
  
  <div class="card">
    <img src="https://picsum.photos/200/100" alt="..." class="card-img-top">
    <div class="card-body">
      <h2 class="card-title">Selectable Title 2</h2>
      <p>
        You can select this text even though the whole card is clickable. <a href="#2">Read more...</a>
      </p>
    </div>
  </div>
  
  <div class="card">
    <img src="https://picsum.photos/200/100" alt="..." class="card-img-top">
    <div class="card-body">
      <h2 class="card-title">Selectable Title 3</h2>
      <p>
        You can select this text even though the whole card is clickable. <a href="#3">Read more...</a>
      </p>
    </div>
  </div>
  
  <div class="card">
    <img src="https://picsum.photos/200/100" alt="..." class="card-img-top">
    <div class="card-body">
      <h2 class="card-title">Selectable Title 4</h2>
      <p>
        You can select this text even though the whole card is clickable. <a href="#4">Read more...</a>
      </p>
    </div>
  </div>
</div>
.cards {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  margin: 37px auto 0;
  width: calc(280px * 4);
}

.card {
  box-shadow: 0 3px 10px 0 #aaa;
  cursor: pointer;
  height: 280px;
  position: relative;
  width: 243px;
}

.card h2 {
  font-size: 20px;
  font-weight: bold;
}

.card.visited {
  box-shadow: 0 3px 10px 2px #444;
}

@media (max-width: 1100px) {
  .cards {
    grid-template-columns: 1fr 1fr;
    width: calc(280px * 2);
  }
  .card {
    margin: 0 auto 2rem;
  }
}

@media (max-width: 768px) {
  .cards {
    display: block;
    width: 100vw;
  }
  .card {
    margin: 0 auto 2rem;
  }
}
clickAndSelect()

function clickAndSelect() {
  let cards = Array.from( document.querySelectorAll('.card') ),
      elements = []
  
  // Add child nodes to clickable elements
  cards.forEach(card => {
    elements = elements.concat( Array.from(card.children) )
  })

  // Attach to mouse events
  elements.forEach(element => {
    
    // click: Disable
    element.addEventListener('click', e => e.preventDefault())
    
    // mousedown: Log the timestamp
    element.addEventListener('mousedown', e => {
      let card = e.target.closest(".card")
      card.setAttribute('data-md', Date.now())
    })
    
    // mouseup: Determine whether to click
    element.addEventListener('mouseup', e => {
      
      // Only one please
      e.stopPropagation();

      let card = (e.target.classList.contains("card")) ? e.target : e.target.closest('.card'),
          then = card.getAttribute('data-md'),
          now = Date.now()

      // Allow 200ms to distinguish click from non-click
      if(now - then < 200) {
        
        // Visit the link in the card
        // Change 'a' to a class if you have multiple links
        window.location = card.querySelector('a').href
    
        // Remove for production
        card.classList.add('visited')
        console.log(card.querySelector('a').href)
        
      }
  
      // Clean up
      card.removeAttribute('data-md')
      
    })
  })
}

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.