You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails中实现Google Font选择表单并加载到CSS?

Hey there! Great question—your initial idea of using an <input> paired with a <datalist> for Google Font selection is totally feasible, and it’s a lightweight, no-fuss way to implement this in Rails. Let’s walk through how to build this end-to-end, step by step.


1. First: Confirm Feasibility

Your core approach works perfectly. The <datalist> element is native HTML with excellent browser support, so it doesn’t require heavy JS libraries or plugins. It’s ideal for a simple, searchable font picker where you don’t need advanced features like real-time previews (though we can add that later if you want!).


2. Step-by-Step Implementation

2.1 Fetch & Cache Google Fonts (Backend)

You don’t want to hardcode every Google Font—they update regularly. Instead, pull the official list via Google’s Web Fonts API and cache it to avoid hitting rate limits.

First, grab an API key from the Google Cloud Console (enable the Web Fonts API for your project). Then add this logic to your controller (we’ll use ApplicationController so the font list is available everywhere):

# app/controllers/application_controller.rb
before_action :fetch_google_fonts

def fetch_google_fonts
  # Cache the font list for 1 week to reduce API calls
  @google_fonts = Rails.cache.fetch('google_fonts', expires_in: 1.week) do
    require 'net/http'
    require 'json'
    api_url = URI("https://www.googleapis.com/webfonts/v1/webfonts?key=YOUR_GOOGLE_API_KEY")
    response = Net::HTTP.get(api_url)
    font_data = JSON.parse(response)
    # Extract just the font family names (e.g., "Roboto", "Open Sans")
    font_data['items'].map { |font| font['family'] }
  rescue StandardError
    # Fallback to a default list if API fails
    ["Roboto", "Open Sans", "Inter", "Lato", "Montserrat"]
  end
end

2.2 Build the Font Selection Form

Fix up your initial form code—you need to link the <input> to the <datalist> using the list attribute. Here’s a reusable ERB partial:

# app/views/shared/_font_selector.html.erb
<%= form_with(model: current_user, url: update_font_path, method: :patch) do |form| %>
  <div class="font-picker">
    <%= form.label :selected_font, "Pick a Google Font:", class: "block mb-2" %>
    <%= form.text_field :selected_font, 
                        list: "google-fonts", 
                        placeholder: "Type to search...",
                        class: "px-4 py-2 border rounded" %>
    <datalist id="google-fonts">
      <% @google_fonts.each do |font_family| %>
        <option value="<%= font_family %>"><%= font_family %></option>
      <% end %>
    </datalist>
    <%= form.submit "Apply Font", class: "mt-3 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" %>
  </div>
<% end %>

2.3 Store the Selected Font

Add a field to your user model to save the chosen font:

rails generate migration AddSelectedFontToUsers selected_font:string
rails db:migrate

Optional: Add a soft validation to ensure the selected font is valid (skip this if you want to allow custom entries):

# app/models/user.rb
validates :selected_font, allow_blank: true, inclusion: { 
  in: ->(_) { Rails.cache.fetch('google_fonts') },
  message: "is not a valid Google Font"
}

2.4 Load the Font Dynamically in Your Layout

Add a dynamic Google Fonts link tag to your application layout, plus apply the font to your site’s CSS:

# app/views/layouts/application.html.erb
<head>
  <!-- Dynamic Google Font Link -->
  <% if current_user&.selected_font.present? %>
    <link href="https://fonts.googleapis.com/css2?family=<%= URI.encode(current_user.selected_font) %>:wght@400;500;700&display=swap" rel="stylesheet">
  <% else %>
    <!-- Fallback default font -->
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
  <% end %>

  <!-- Apply the font via inline CSS (or use SCSS with ERB) -->
  <style>
    body {
      font-family: <%= current_user&.selected_font || 'Inter' %>, sans-serif;
    }
  </style>

  <!-- Rest of your head content -->
</head>

2.5 Handle Form Submission

Add a controller action to update the font and a route:

# app/controllers/users_controller.rb
def update_font
  if current_user.update(selected_font: params[:user][:selected_font])
    redirect_back fallback_location: root_path, notice: "Font updated successfully!"
  else
    redirect_back fallback_location: root_path, alert: "Invalid font selection."
  end
end
# config/routes.rb
patch '/update-font', to: 'users#update_font', as: 'update_font'

3. Optional Enhancements (If You Want More)
  • Real-time preview: Add a JS listener to the input field that updates a preview div’s font-family as the user types/selects.
  • Font weight selection: Add a dropdown for weights (400, 700, etc.) and update the Google Fonts link to include them.
  • Category filtering: If you want to let users filter fonts by category (serif, sans-serif), modify the API call to include category data and add a filter dropdown.

Final Feasibility Check

Your original approach is not just feasible—it’s a smart, low-overhead solution for basic font selection. If you only need a simple searchable picker, this will work perfectly. For more complex workflows, you could swap in a JS library like react-google-fonts-picker, but that’s overkill for most use cases.

内容的提问来源于stack exchange,提问作者Gyntonic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:53:08