I want to make the blogs list page to display all the blog
here is my html code:
<style>
  /* Categories horizontal scroll container (unchanged) */
  .categories {
    /* BASE styles for all screen sizes */
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 0.5rem;
    padding: 0 1rem;
    background: #121535;
    width: 100%;
    justify-content: flex-start;
    position: static;
    margin-left: 0;
    margin-right: 0;
    left: auto;
    right: auto;
    box-sizing: border-box;
    touch-action: pan-x;
  }

  /* Hide scrollbars */
  .categories::-webkit-scrollbar {
    display: none;
  }

  /* WIDE SCREENS: Apply the centering and full viewport width */
  @media (min-width: 900px) {
    .categories {
      position: relative;
      left: 50%;
      right: 50%;
      margin-left: -50vw;
      margin-right: -50vw;
      width: 100vw;
      box-sizing: border-box;
      padding: 0 1rem;
      background: #121535;

      justify-content: center;
    }
  }


  .category-item {
    flex: 0 0 auto;
    background: #121535;
    color: white;
    /*min-width: 80px;*/
    padding: 0.5rem 0.75rem;
    font-size: 0.9rem;
    white-space: nowrap;
    user-select: none;
    cursor: pointer;
    transition: background-color 0.3s ease;
    border: none;
  }
  .category-item:hover,
  .category-item:focus {
    background: #0056b3;
    outline: none;
  }

  /* ARTICLES GRID LAYOUT */
  .articles {
    margin-top: 0.5rem;
    display: grid;
    gap: 1rem;
    /* Mobile default: 1 column */
    grid-template-columns: 1fr;
  }

  /* Tablets: 2 columns */
  @media (min-width: 600px) {
    .articles {
      grid-template-columns: repeat(2, 1fr);
      gap: 1.2rem;
    }
  }

  @media (min-width: 1200px) {
    .articles {
      grid-template-columns: repeat(3, 1fr);
      gap: 1.5rem;
    }
  }

  /* Desktop: 4 columns */
  @media (min-width: 1600px) {
    .articles {
      grid-template-columns: repeat(4, 1fr);
      gap: 1.5rem;
    }
  }

  /* ARTICLE ITEM – updated layout */
  article.article-item {
    display: flex;
    flex-direction: column;
    background: white;
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
    position: relative;
    min-height: 320px; /* optional for consistent heights, adjust as needed */
  }

  /* IMAGE on top */
  article.article-item img.thumbnail {
    width: 100%;
    height: 180px;
    object-fit: cover;
    flex-shrink: 0;
  }

  /* ARTICLE DETAILS container */
  .article-details {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 0.5rem;
  }

  /* TITLE */
  .article-title {
    font-size: 1rem;
    font-weight: bold;
    margin: 0 0 0.5rem 0;
    line-height: 1.2;
    flex-shrink: 0;
  }

  @media (min-width: 600px) {
    .article-title {
      font-size: 1.1rem;
    }
  }
  @media (min-width: 900px) {
    .article-title {
      font-size: 1.2rem;
    }
  }

  /* TAGS */
  .article-tags {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
  }

  .article-tags span {
    background: #d4edda;
    color: #155724;
    border-radius: 12px;
    padding: 0.15rem 0.6rem;
    font-size: 0.75rem;
    display: inline-block;
  }

  /* CATEGORIES */
  .article-categories {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-bottom: auto; /* push date to bottom */
  }

  .article-categories span {
    background: #cce5ff;
    color: #004085;
    border-radius: 12px;
    padding: 0.15rem 0.6rem;
    font-size: 0.75rem;
    display: inline-block;
  }

  /* PUBLISHED DATE at bottom */
  .published-date {
    font-size: 0.85rem;
    color: #999;
    margin-top: 1rem;
    flex-shrink: 0;
  }

  @media (min-width: 600px) {
    .published-date {
      font-size: 0.9rem;
    }
  }
  @media (min-width: 900px) {
    .published-date {
      font-size: 0.95rem;
    }
  }
</style>

<!-- ========================= Breadcrumb Start =============================== -->
<div class="breadcrumb mb-0 py-26 bg-color-one">
  <div class="container container-lg">
    <div class="breadcrumb-wrapper flex-between flex-wrap gap-16">
      <h6 class="mb-0">文章</h6>
      <ul class="flex-align gap-8 flex-wrap">
        <li class="text-sm">
          <a href="<?= base_url() ?>" class="text-main-600 flex-align gap-8">
            <i class="ph ph-house"></i>
            主頁
          </a>
        </li>
        <li class="flex-align text-gray-500">
          <i class="ph ph-caret-right"></i>
        </li>
        <li class="text-sm text-neutral-600">
          文章
        </li>
      </ul>
    </div>
  </div>
</div>
<!-- ========================= Breadcrumb End =============================== -->


<!-- Categories horizontal scroll list -->
<nav class="categories" aria-label="Article categories">
  <button class="category-item" type="button">All</button>
  <button class="category-item" type="button">Technology</button>
  <button class="category-item" type="button">Health</button>
  <button class="category-item" type="button">Science</button>
  <button class="category-item" type="button">Business</button>
  <button class="category-item" type="button">Travel</button>
  <button class="category-item" type="button">Education</button>
  <button class="category-item" type="button">Sports</button>
  <button class="category-item" type="button">Entertainment</button>
  <button class="category-item" type="button">Lifestyle</button>
</nav>

<div class="container container-lg">
  <!-- Articles list -->
  <section class="articles" aria-label="Article list">
    <article class="article-item">
      <img src="https://picsum.photos/400/300" alt="Article thumbnail" class="thumbnail" />
      <div class="article-details">
        <h2 class="article-title">How Technology is Changing the Modern World</h2>
        <div class="article-tags" aria-label="Tags">
          <span>AI</span><span>Innovation</span><span>Future</span>
        </div>
        <div class="article-categories" aria-label="Categories">
          <span>Technology</span><span>Science</span>
        </div>
        <time class="published-date" datetime="2024-06-15">2024-06-15</time>
      </div>
    </article>

    <article class="article-item">
      <img src="https://picsum.photos/400/300" alt="Article thumbnail" class="thumbnail" />
      <div class="article-details">
        <h2 class="article-title">10 Tips for a Healthy Lifestyle</h2>
        <div class="article-tags" aria-label="Tags">
          <span>Wellness</span><span>Nutrition</span>
        </div>
        <div class="article-categories" aria-label="Categories">
          <span>Health</span><span>Lifestyle</span>
        </div>
        <time class="published-date" datetime="2024-05-20">2024-05-20</time>
      </div>
    </article>

    <article class="article-item">
      <img src="https://picsum.photos/400/300" alt="Article thumbnail" class="thumbnail" />
      <div class="article-details">
        <h2 class="article-title">Exploring the Wonders of Space Travel</h2>
        <div class="article-tags" aria-label="Tags">
          <span>Space</span><span>Exploration</span>
        </div>
        <div class="article-categories" aria-label="Categories">
          <span>Science</span><span>Travel</span>
        </div>
        <time class="published-date" datetime="2024-04-10">2024-04-10</time>
      </div>
    </article>

    <!-- Add more article items as needed -->
  </section>
</div>


And I also want this support dynamic content with server-side loaded data. The data will come from the following functions:
Categories:
public function get_categories($id = NULL, $limit = '', $offset = '', $sort = 'row_order', $order = 'ASC', $has_child_or_item = 'true', $slug = '', $ignore_status = '', $seller_id = '')
    {
        $level = 0;
        if ($ignore_status == 1) {
            $where = (isset($id) && !empty($id)) ? ['c1.id' => $id] : ['c1.parent_id' => 0];
        } else {
            $where = (isset($id) && !empty($id)) ? ['c1.id' => $id, 'c1.status' => 1] : ['c1.parent_id' => 0, 'c1.status' => 1];
        }

        $this->db->select('c1.*');
        $this->db->where($where);
        if (!empty($slug)) {
            $this->db->where('c1.slug', $slug);
        }

        if (!empty($limit) || !empty($offset)) {
            $this->db->offset($offset);
            $this->db->limit($limit);
        }

        $this->db->order_by($sort, $order);

        $parent = $this->db->get('categories c1');
        $categories = $parent->result();
        $count_res = $this->db->count_all_results('categories c1');
        $i = 0;
        foreach ($categories as $p_cat) {
            $categories[$i]->text = output_escaping($p_cat->name);
            $categories[$i]->name = output_escaping($categories[$i]->name);
            $categories[$i]->state = ['opened' => true];
            $categories[$i]->icon = "jstree-folder";
            $categories[$i]->level = $level;
            $categories[$i]->image = get_image_url($categories[$i]->image, 'thumb', 'sm');
            $categories[$i]->banner = get_image_url($categories[$i]->banner, 'thumb', 'md');
            $i++;
        }
        if (isset($categories[0])) {
            $categories[0]->total = $count_res;
        }
        return  json_decode(json_encode($categories), 1);
    }

Blogs:
function get_blogs($offset, $limit, $sort, $order, $search = NULL, $category_id = NULL)
    {
        $blog_data = [];
        $multipleWhere = '';

        $where['status'] = '1';
        if (isset($category_id) && !empty($category_id)) {
            $where['category_id'] = $category_id;
        }
        if (isset($search) and $search != '') {
            $multipleWhere = ['title' => $search, 'slug' => $search];
        }

        $count_res = $this->db->select(' COUNT(id) as `total` ');
        if (isset($multipleWhere) && !empty($multipleWhere)) {
            $count_res->group_start();
            $count_res->or_like($multipleWhere);
            $count_res->group_end();
        }
        if (isset($where) && !empty($where)) {
            $count_res->where($where);
        }
        $count_res = $count_res->get('blogs')->result_array();
        $search_res = $this->db->select(' * ');
        if (isset($multipleWhere) && !empty($multipleWhere)) {
            $search_res->group_start();
            $search_res->or_like($multipleWhere);
            $search_res->group_end();
        }
        if (isset($where) && !empty($where)) {
            $search_res->where($where);
        }
        $search_res = $search_res->order_by((string)$sort, (string)$order)->limit($limit, $offset)->get('blogs')->result_array();
        if (!empty($search_res)) {
            for ($i = 0; $i < count($search_res); $i++) {
                $search_res[$i] = output_escaping($search_res[$i]);
            }
        }
        $blog_data['total'] = $count_res[0]['total'];
        $blog_data['data'] = $search_res;
        return  $blog_data;
    }

And they will call and stored in:
$this->data['blogs'] = $this->blog_model->get_blogs($offset, $limit, 'id', 'DESC', $blog_search, $category_id);
$this->data['fetched_data'] = fetch_details('blog_categories');

The front-end can call blogs to get the data from get_blogs, and call fetched_data to get the data from blog_categories